Musique vs other programming languages cheatsheet

This commit is contained in:
Robert Bendun 2022-09-21 16:42:18 +02:00
parent 34eb56ac50
commit f42e700747
3 changed files with 262 additions and 0 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ drafts.cc
.cache .cache
release_* release_*
*.zip *.zip
*.html

View 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

View 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()