Musique vs other programming languages cheatsheet
This commit is contained in:
parent
34eb56ac50
commit
f42e700747
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ drafts.cc
|
||||
.cache
|
||||
release_*
|
||||
*.zip
|
||||
*.html
|
||||
|
121
doc/musique-vs-languages-cheatsheet.template
Normal file
121
doc/musique-vs-languages-cheatsheet.template
Normal file
@ -0,0 +1,121 @@
|
||||
TITLE Porównanie Musique z typowymi językami programowania
|
||||
|
||||
BEGIN CSS
|
||||
table, tr, td {
|
||||
font-size: 12pt;
|
||||
border: 1pt solid #DDDDDD;
|
||||
border-collapse: collapse;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
END CSS
|
||||
|
||||
BEGIN INTRO
|
||||
<h1>Ściągawka Musique, a Python i Ruby</h1>
|
||||
Ponieważ Musique jest kierowany do osób posiadających doświadczenie z muzyką algorytmiczną, szybkim sposobem na podstawowe poznanie języka jest porównanie z innymi technologiami w tej dziedzinie. Ten dokument służy bardziej ukazaniu różnic niż omówieniu samego języka.
|
||||
END INTRO
|
||||
|
||||
BEGIN TABLE
|
||||
|
||||
n Kategoria
|
||||
m Musique
|
||||
p Python
|
||||
r Ruby (SonicPi)
|
||||
c Komentarz
|
||||
|
||||
n Deklaracja
|
||||
m x := 0
|
||||
p x = 0
|
||||
r x = 0
|
||||
c Zmienne należy zadeklarować by móc z nich korzystać
|
||||
|
||||
n Aktualizacja
|
||||
m x = 1
|
||||
r x = 1
|
||||
p x = 1
|
||||
|
||||
n Operacje matematyczne
|
||||
m x = 10 * 30 - 40 ** 2
|
||||
p x = 10 * 30 - 40 ** 2
|
||||
r x = 10 * 30 - 40 ** 2
|
||||
c Zarówno Python, Ruby jak i Musique posiadają operator potęgi **
|
||||
|
||||
n Funkcja anonimowa
|
||||
m add := [x y | x + y]
|
||||
p add = lambda x, y: x + y
|
||||
r add = ->(x, y) { x + y }
|
||||
|
||||
n Deklaracja funkcji
|
||||
m add := [x y |
|
||||
m say x y;
|
||||
m x + y
|
||||
m ]
|
||||
p def add(x, y):
|
||||
p print(x, y)
|
||||
p return x + y
|
||||
r def add(x, y)
|
||||
r puts x, y
|
||||
r return x + y
|
||||
r end
|
||||
c Musique nie rozróżnia funkcji anonimowych i zadeklarowanych
|
||||
|
||||
n Tablice
|
||||
m x = [1; 2; 3; 4]
|
||||
p x = [1, 2, 3, 4]
|
||||
r x = [1, 2, 3, 4]
|
||||
|
||||
n Nty element tablicy
|
||||
m x.n
|
||||
p x[n]
|
||||
r x[n]
|
||||
|
||||
n Aktualizacja ntego elementu tablicy
|
||||
m x = update x n 10
|
||||
p x[n] = 10
|
||||
r x[n] = 10
|
||||
|
||||
n Tablica od 0 do 9 włącznie
|
||||
m x = up 10
|
||||
p x = range(10)
|
||||
r x = [*0..9]
|
||||
|
||||
n Tablica od 1 do 10 włącznie
|
||||
m x = 1 + up 10
|
||||
m lub x = range 1 11
|
||||
p x = range(1, 11)
|
||||
r x = [*1..10]
|
||||
|
||||
n Iloczyn elementów tablicy
|
||||
m fold '* (1 + up 5)
|
||||
p functools.reduce(
|
||||
p operator.mul, range(1, 6), 1)
|
||||
r [*1..5].inject(:*)
|
||||
c Musique pozwala zmienić dowolny operator w funkcję
|
||||
c poprzez zapis 'operator jak '* w przykładzie
|
||||
|
||||
n Instrukcja warunkowa
|
||||
m if (n == 42)
|
||||
m [ say 1 ]
|
||||
m [ say 2 ]
|
||||
p if n == 42:
|
||||
p print(1)
|
||||
p else:
|
||||
p print(2)
|
||||
r if n == 42
|
||||
r puts 1
|
||||
r else
|
||||
r puts 2
|
||||
r end
|
||||
c Musique nie posiada instrukcji warunkowej, a funkcję if,
|
||||
c która przyjmuje wartość logiczną i dwa bloki (funkcje anonimowe)
|
||||
c - jeden z nich zostanie wykonany jeśli warunek jest prawdziwy,
|
||||
c a drugi jeśli jest fałszywy.
|
||||
n Wyrażenie warunkowe
|
||||
m x := if (n == 42) [1] [2]
|
||||
p x = 1 if n == 42 else 2
|
||||
r x = n == 42 ? 1 : 2
|
||||
END TABLE
|
140
scripts/language-cmp-cheatsheet.py
Normal file
140
scripts/language-cmp-cheatsheet.py
Normal file
@ -0,0 +1,140 @@
|
||||
import argparse
|
||||
import os
|
||||
import string
|
||||
import collections
|
||||
|
||||
Directive = collections.namedtuple("Directive", "line_number type content")
|
||||
|
||||
HTML_TEMPLATE = string.Template("""<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>$title</title>
|
||||
<style>$css</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>$intro</p>
|
||||
<table> $table </table>
|
||||
</body>
|
||||
</html>
|
||||
""")
|
||||
|
||||
def parse_table(lines: list):
|
||||
previus_column_type = None
|
||||
rows, order = [{}], []
|
||||
current_row = rows[0]
|
||||
|
||||
# Each nonblank matches this regular expression /(\S*)\s(.*)/
|
||||
# where first capture is type of column (essentialy column id) and
|
||||
# second capture is given cell content. Where column type repeats not in row
|
||||
# we have new row.
|
||||
for line in lines:
|
||||
if not line:
|
||||
continue
|
||||
|
||||
sep = line.find(' ')
|
||||
column_type, cell_content = line[:sep].strip(), line[sep:]
|
||||
|
||||
if column_type not in order:
|
||||
order.append(column_type)
|
||||
|
||||
if previus_column_type != column_type and column_type in current_row:
|
||||
rows.append({})
|
||||
current_row = rows[-1]
|
||||
|
||||
cell = current_row.get(column_type, [])
|
||||
cell.append(cell_content)
|
||||
current_row[column_type] = cell
|
||||
previus_column_type = column_type
|
||||
|
||||
# Eliminate common whitespace prefix in given column type (not all whitespace
|
||||
# prefix since examples in Python may have significant whitespace)
|
||||
for row in rows:
|
||||
for cell in row.values():
|
||||
prefix_whitespace = min(len(s) - len(s.lstrip()) for s in cell)
|
||||
for i, s in enumerate(cell):
|
||||
cell[i] = s[prefix_whitespace:]
|
||||
|
||||
return rows, order
|
||||
|
||||
def compile_template(*, template_path: str, target_path: str):
|
||||
# Read template file and separate it into lines
|
||||
with open(template_path) as f:
|
||||
template = [line.strip() for line in f.readlines()]
|
||||
|
||||
directives = []
|
||||
for i, line in enumerate(template):
|
||||
s = line.split()
|
||||
if s and s[0] in ("BEGIN", "END", "TITLE"):
|
||||
directives.append(Directive(i, s[0], line[len(s[0]):].strip()))
|
||||
|
||||
title, css_source, table_source, intro_source = 4 * [None]
|
||||
|
||||
for directive in directives:
|
||||
if directive.type == "TITLE":
|
||||
title = directive.content
|
||||
continue
|
||||
|
||||
if directive.type == "BEGIN":
|
||||
start_line = directive.line_number
|
||||
for end in directives:
|
||||
if end.type == "END" and end.content == directive.content:
|
||||
end_line = end.line_number
|
||||
break
|
||||
else:
|
||||
assert False, "Begin without matching end"
|
||||
|
||||
span = template[start_line+1:end_line]
|
||||
|
||||
if directive.content == "CSS":
|
||||
css_source = span
|
||||
elif directive.content == "TABLE":
|
||||
table_source = span
|
||||
elif directive.content == "INTRO":
|
||||
intro_source = span
|
||||
|
||||
assert css_source is not None
|
||||
assert table_source is not None
|
||||
assert intro_source is not None
|
||||
assert title is not None
|
||||
|
||||
rows, columns_order = parse_table(lines=table_source)
|
||||
|
||||
table = ""
|
||||
|
||||
for i, row in enumerate(rows):
|
||||
if i == 0:
|
||||
line = ["<th>" + ' '.join(row[k]) + "</th>" for k in columns_order]
|
||||
else:
|
||||
line = []
|
||||
for column in columns_order:
|
||||
val = row.get(column, [])
|
||||
line.append('<td><pre><code>' + '<br/>'.join(val) + '</code></pre></td>')
|
||||
|
||||
table += "<tr>\n" + '\n'.join(line) + "\n</tr>\n"
|
||||
|
||||
|
||||
final = HTML_TEMPLATE.substitute({
|
||||
"title": title,
|
||||
"css": "\n".join(css_source),
|
||||
"table": table,
|
||||
"intro": "\n".join(intro_source)
|
||||
})
|
||||
|
||||
with open(target_path, "w") as f:
|
||||
f.write(final)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Build language comparison chart")
|
||||
parser.add_argument(nargs='+', metavar="TEMPLATE", dest="templates", help="Template file that will be converted to HTML page")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
for template in args.templates:
|
||||
dst, _ = os.path.splitext(template)
|
||||
dst += ".html"
|
||||
compile_template(template_path=template, target_path=dst)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user