proj-oot-ootSyntaxNotes3

might want a syntax for 'apply this code transformation with the scope of this entire function'. Eg might want to say: ^ref a to declare that the variable 'a' will be addressed by reference, eg:

a = 3 y = f(a)

should be transformed to:

(and of course the language is handling memory management and initialization here)

---

i guess one principal of Oot syntax is that we eschew keywords and use punctuation instead for core language language-y things (but not just for primitive operations, like Hoon does). This has a few benefits:

---

when i explain my idea that local mutations are okay, but what you don't want is aliasing between variables across different functions, i use the demonstration that:

a = 3 a = f(3) y = g(a)

can be transformed into

a_1 = 3 a_2 = f(a_1) y = g(a_2)

that is, go thru the fn one line at a time, and upon each assignment to a, increment a counter i and then do a search-and-replace over the rest of the fn below that line, replacing a with a_i

note that this is a local (function-local) transformation.

i notice that my proposal for reference variables is also such a transformation. And that i proposed a syntax like ^ref for that transformation.

this suggests that we should let the user define other transformations and apply them eg ^users-custom-transform-name to the function scope.

---

consideration of the 'function scope' brings into focus the point that in Haskell and Lisp, there is no 'function scope', there are just expressions, some of which produce first-class functions which are bound to identifiers.

so i guess part of the (syntactic) idea of these languages is that there is no such thing syntactically as a 'block' of statements, there are only expression trees. But both of them actually provide block-like constructs, do notation in haskell and progn in lisp.

so this is an argument for us providing blocks.

the opposite conception might be eg javascript, where variable declaration 'hoisting' use function scopes.

functions of course are 'above' blocks in a sense, in that you might have a sub-block within a function, syntactically, eg if you have blocks delimiting then/else in an if/then/else, or delimiting a while loop, etc. Most likely ppl would like transformations such as mutable variables and by-reference variables to be function-level, not just block-level.

so perhaps we should provide function scoping for this.

---

F# has an interesting, straightforward syntax for declaring properties:

public class PiggyBank?{ public PiggyBank?(int coins){ Coins = coins; }

  public int Coins { get; set; }}

(from https://msdn.microsoft.com/en-us/magazine/ee336127.aspx )

now, i think everything should be properties in Oot, but the F# syntax is still neat/worth noting.

---

mb no need to waste uppercase on labels, labels are rare, so mb we can use uppercase just to distinguish keywords from annotations?

---

if we have annotations, maybe eg "^ref a" can mean that ^ref is an annotation. Or maybe "^ref(a)" is better to make it clear that 'a' is not in the base part of the AST (it's part of the annotation).

And mb just use uppercase for annotations:

REF(a)

(leaving capitalization for keywords: f(Keyword-a))

nah, let's have upper for keywds and caps for annotations:

Ref(a)

f(KEYWORD-A)

---

y'know, could distinguish multiple grouping constructs from one symbol by repeating the opening two or more times in a row, since there's never a reason to do that 'for real'. Eg [[image: ?]] could be different from { }. And (( )) vs ( ).

to make that easier to remember, the multiple repeats could only be used for 'big' versions of the single ones.

eg maybe use (( )) for 'parens until explicit close' (as opposed to ordinary parens, ( ), which are implicitly closed at the end of a paragraph). And maybe use [[image: ?]] for 'big block', which functions like a 'function scope' in that many metaprogramming constructs are implicitly scoped to the enclosing big block.

---

colon for namespace prefixing? or just period?

---

should a trailing period, eg 'y.fieldname.' mean anything?

some ideas:

---

so far i like the assertion the best

---

mb y..fieldname is the syntax for referring to the edge connecting 'y' and 'fieldname' and how, then, to refer to the ports of this edge? mb: e = y..fieldname; psrc = ..e; pdst = e.. yeah i like that. any use for y.fieldname. now? is a port really just a second order edge? what about roles for hyperedges? my guess is: yes; hyperedges need more syntax, this is just convenient syntax for the typical case of ordinary edges (mb the syntax for hyperedges is y.(role).edgenamee; no wait arent roles just like fields in the reified edge anyways?

---

" let squareOfEvens = numbers

> Seq.filter IsEven?
> Seq.map Square

The only confusing part about this code may be the

> operator. This operator is used to make code more readable by allowing you to reorder the arguments to a function so that the last argument is the first thing that you read. Its definition is very simple:

let (

>) x f = f x

Without the

> operator, the squareOfEvens code would look like this:

let squareOfEvens2 = Seq.map Square (Seq.filter IsEven? numbers)

" -- https://msdn.microsoft.com/en-us/magazine/ee336127.aspx

---

actually i guess mb we dont need hypergraphs -- the 'roles' in hyperedges make them just like nodes-as-dicts anyways, no need to have two kinds of entity instead of 1

so we still need a way to select an edge, at least, the trailing edge. So maybe y.edgename. after all (y.edgename selects the destination node, y.edgename. selects the edge itsel)

could use a..b..c to select a path (what about a..b.c..d? a disjoint selection?)

still need a syntax to construct immutable value graphs with cycles (eg without directly using the & ptrs syntax because these are values, not references). Maybe just use && though!

---

discarded idea but mb worth reading over again later:

or, could use & to refer to an edge, too.. perhaps postfix

v.1&.__SRC == v

hey, that's not so bad!

is v.1&& then the meta edge connecting v.1 and v.1&? or perhaps it's a port. v.1&& is the dst side port, v.&&1 is the src side? but why not just one &? and why not use ..? and what if a path contains multiple clusters of &&&s?

mb the trailing period and the forced use of temporary var isnt so bad. itll keep the program less dense/more readable when ascending to thee meta-level of an edge.

---

ruminations leading up two using prefix $ to identify nodes in the rhs of a node constructor:

  1. if you gave thee literal .X at the top level, it might be a first-class reference to variable binding for variable x, or label X, or something like that. how is that different from &x, if at all?

(why r we using = instead of / to bind? is it because the rhs is either an edgelist (if this name is bound to a multiedge node) or an atomic primitive? b/c if we used / then the rhs would be bound to a node name, not a node constructor literal?)

is prefix . within node constructors related to addressof (prefix &)? b/c these are just like variable bindings in code, homoiconicity and all that, right? interesting.. i think it may be different.. levels? its kinda like antiquote/quasiquote, i guess

mb use .prefixperiod again? is .prefixperiod just antiquote/quasiquote? does getting the string value makes this a 'reader macro' or does that mean preparsing?

note: i guess .X, meaning the node with name X, and X., meaning the edgee from root to X, might be symmetric in a buildup/builddown way. and this might be related to quasiquoting.

mb antiquote == interpolate? mb quote should be a leading $, and antiquote a trailing $?

---

from the previous; do still think about antiquote/quasiquote for macros and whether it's connected to these other things

--- so how do we refer to the environment itself? And how do we refer to the enclosing block? Seems like there should be a way combining --ROOT with some metaprogrammy stuff?

before i proposed: So is --ROOT"" the way to refeer to the environment itself (now i think? no)? whereas .--ROOT is a reference to thee enclosing block?

---

mb _ is leveldown, the inveerse of ^

---

the + convention for unary interferes with the idea of +- to denotee uncertainty, but we could just use -+ for that

---

if we're locally eager by default, need cheap syntax for suspend / lazy list construction

---

so is: like /, / like =, : like ^? or something like that?

---

mb inc should be +1 anyways, and dec +-1.


js es6 object literal property value shorthand :

"

Consider the following ECMAScript 5 fragment:

function createMonster(name, power) { return { type: 'Monster', name: name, power: power }; } function createWitch(name) { return { type: 'Witch', name: name }; }

With the new shorthand form, this can be rewritten as the following code:

function createMonster(name, power) { return { type: 'Monster', name, power }; } function createWitch(name) { return { type: 'Witch', name }; }

"

---

could use . for scoping, the way colons : or :: are used in some languages (eg module.name instead of module::name). here we can't use : because we're using it for 'syntactic pseudokeyword' like 'then' and 'else'. or could use : for scoping and something else for 'syntactic pseudokeyword'.

---

"--" is currently open to be assigned to some operator

(hmm, mb this should be this/self/me? or 'x' or 'it'?)

---

in the past, we've discussed using $var as the notation to refer to the VARIABLE $var rather than substitute in its value. But we've also discussed doing this with ?var. So either way, we have a free one.

i guess a this moment i'd prefer to use ?var for 'variable var itself'. So then var? can be 'interpolate'/'antiquote'/'quasiquote'. And maybe we could even use infix ? as the argument/function body separator for function definitions (instead of '):

double = x ? x + x

(note: this is two characters longer than ML style:

double x = x + x

mb that could just be a metaprogrammy transform, though )

---

so lambda functions are just blocks with ?s in them:

{x ? x + x}

---

now $ is free again. mb use for laziness/strictness?

we need a notation for overriding the default of binding all optional arguments to their defaults when partially applying a function. How about '$/'?


could also consider the javascript '=>' syntax to separate argspecs from function bodies. Then we could use '$' for something else.

---

consider what would be needed to make Oot as convenient as Shell. One thing is to make it syntactically convenient to specify files or lists of files or fileglobs. In shell you can just type 'ls something*.txt', as opposed to Python: import glob; glob.glob('something*.txt')

Perhaps one solution is to adapt the Perl idea of having an implicit pronoun/argument (is it '$_' in Perl?). Note that the idea of a 'current working directory' (cwd) is sort of an implicit context in Shell.

The implicit context in Oot could be a graph which is implicitly referenced. The cwd could be changed (cd) by changing the value of this implicit context to a child node (subdirectory) or parent node (containing directory) of the current cwd.

So eg if 'cwd = filesystem('/home/jsmith')', then we'd have some syntax to reference it, perhaps a prefix '.', eg:

cwd = filesystem('/home/jsmith') ;; shortcut: cd /home/jsmith somefiles = .something*.txt ;; implicitly refers to the list of files given by: filesystem('/home/jsmith/something*.txt') somefiles2 = .something*.txt , .somethingElse*.txt ;; implicitly refers to the list of files given by: filesystem('/home/jsmith/something*.txt') + filesystem('/home/jsmith/somethingElse*.txt')

---

" :- module(_, _, [functional, lazy]). ... In Ciao, the first and second arguments of a module declaration (line 1) hold the module name and list of exports in the standard way. “ ” in the first argument means that the name of the module is the name of the file, without suffix, and in the second one that all definitions are exported. The third argument states a list of packages to be loaded ( functional and lazy in this case, which provide functional notation and lazy evaluation). "

" Packages are Ciao files that contain syntax and compilation rules and that are loaded by the compiler as plugins and unloaded when compilation finishes. Packages only modify the syntax and semantics of the module from where they are loaded, and therefore, other modules can use packages introducing incompatible syntax/semantics without clashing. "

--- http://clip.dia.fi.upm.es/papers/hermenegildo11:ciao-design-tplp.pdf

---

maybe eg

py[[image:python code?]]

for character-level meta

---

the example in http://llvm.org/docs/SourceLevelDebugging.html#object-lifetimes-and-scoping seems to show something like our 'footnotes' using a ! prefix sigil

" ... call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !13), !dbg !14 ... !14 = !DILocation(line: 2, column: 9, scope: !4) "

" All metadata has the metadata type and is identified in syntax by a preceding exclamation point ('!'). A named metadata is a collection of metadata nodes, which can be looked up in the module symbol table. For example: "!foo = metadata !{!4, !3}". Metadata can be used as function arguments. Here llvm.dbg.value function is using two metadata arguments.

       call void @llvm.dbg.value(metadata !24, i64 0, metadata !25)Metadata can be attached with an instruction. Here metadata !21 is attached with add instruction using !dbg identifier. %indvar.next = add i64 %indvar, 1, !dbg !21 " -- http://llvm.org/releases/2.7/docs/LangRef.html

this suggests that eg the 3 in #3 (footnote 3) should just be an identifier (locally scoped, i guess? or at least shadowed by local scope redefinition, or most recent redefinition), except that numbers are allowed as identifiers here, and that we just use '#3 = ' as the footnote definition syntax, so we have something like:

  1. 3: doSomething ...
  2. 3 = if (errorCondition): handleError else: it!

where it is a variable to which the body of the thing following the colon in #3 to EOL is assigned as a block (a special syntax of #_: where _ is any identifier) (and ! means 'run the block'). But it's not quite an ordinary block, i guess it's a closure, since it can access and mutate variables in its original lexical context.

something i dont like about this is that typing both # and : is laborious, possibly discouraging its use.

how about this to-EOL behavior is default for #, and can be prevented by enclosing it in explicit parens, so really it is to-end-of-current-explicit-grouping:

  1. 3 doSomething ...
  2. 3 = if (errorCondition): handleError else: it!

would it be better to be:

doSomething #3 ...

  1. 3 = if (errorCondition): handleError else: it!

maybe; that would seem to make the indentation easier

in which case, can you have # in the middle of an expression?

f (g (doSomething #3)) ---> f (g (if (errorCondition) handleError ELSE/doSomething))

f (g doSomething #3 y) ---> f ((if (errorCondition) handleError ELSE/(g doSomething)) y)

i think YES

---

yknow what, just get rid of to-EOL metas, they are a small convenience and a small complexity, but let's get rid of that complexity. Python did.

---

haskell has a neat fn defn syntax where you can say eg:

f a b = a + b

that is, the 'f', 'a', 'b' on the left-hand side are not substituted in with current assignments to values in the current scope, but are instead, because they are on the lhs, regarded as the function name and its formal parameters

we cant do that because we want to unify arrays and fns, and we want to use "a x = b" to 'mutate' element x of array a to value b; so x has to be substituted in

so, we have our backticks syntax. But an alternative would be to use our 'variable' sigil, $, to denote formal parameters:

f $a $b = a + b

this is more typing, but it is strangely attractive; it may be more readable than `f a b` = a + b, or than f `a b` = a + b. Otoh it is less copy-pastable; you can't just copy "f $a $b" into a location where you want to call f

---

i guess "+=" and the like are convenient but add complexity. So don't have them.

later: nah

---

some things it should be easy to find about each variable when reading:

"how the variable is used, its bounds, its legal values, its implied/displayed number of decimal points, its units of measure, its display format, its data entry rules (e.g. total fill, must enter), when its value can be trusted" -- https://www.thc.org/root/phun/unmaintain.html

---

"repeat" is better than "for" (but mb we'd use "rep"?)

"evidence that students find the word “for” unintuitive, and that “repeat” better describes the looping behavior. As there are languages that utilize the keyword “repeat” (Logo in particular comes to mind)," -- Using Commutative Assessments to Compare Conceptual Understanding in Blocks-based and Text-based Programs by David Weintrop and Uri Wilensky

done

---

maybe have a prefix sigil '!' for impure operations after all (or mb ! for side-effectful and ? for nondeterministic); but with the proviso that certain state domains can be omitted when they are 'masked', eg by default the logging state domain and the error state domain and the cache state domain are omitted (and the debug state domain is omitted when in debug mode). So, WITHIN logging code, calls to file I/O routines are still prefixed to ! (b/c from the point of view of the logging module, the file I/O domain is not masked); but in ordinary code, calls to functions that have logging are not prefixed with '!', because the logging state domain is masked.

---

mb use backquote for AST quote

done

---

should fn application have preceddeence overbinary operators, like in haskell? what about the oneletter macros?

done

---

each line is either (a) an assignment, (b) a mutations, or (c) an assertion (just an expression)

done

---

V is for View; no syntax, frees @ to be used for something else (mb something to do with binding; haskell atbindings? but cant we already do that with just uppercas labels?)

mb @ for modal adjectives like r vs w, capagbilities, etc (later: no; see next line)

(a little later: no, it seems like we are using UPPERCASE for keywords, and Capitalized for annotations. So we still need something for labeling; so use @ for that, i guess)

done

---

how would "inplace" annotations work syntactically? i guess they'd surround (be in the parent AST node of) an expreession? mb keep += (x=)

done

---

mb use attached prefix ## instead of @ for labels?

---

" Parentheses - The Horror, The Horror

If you look around at various Clojure articles you’ll find lots of folk downplaying the affect of Lisp parentheses and prefix notation on code readability. Personally, I think that is nonsense; at least for those new to the language.

Most of us have grown-up with languages where we read left-to-right, and where infix notation is the general way maths and logic operators are expressed. It is ingrained in us. The use of s-expressions2 and their resulting prefix notation is in many respects the secret sauce of Clojure. However, it requires you to read right-to-left3 and inside-out. This is counterintuitive to most of us, and takes some getting over. It is a very real barrier to entry for Lisps.

For example, here is some noddy code in Clojure. It just takes a range of numbers, adds two to each of them, and then sums the resulting numbers together.

(reduce + (map (comp inc inc) (range 1 11))) view raw noddy-clojure.clj hosted with ❤ by GitHub?

It’s about as simple as it’s ever going to get. Yet, for those who are not well versed in reading Lisp code, it’s not easy to digest3. Compare it to the equivalent Scala code, below. Make your own mind up.

(1 to 10).map(_ + 2).reduce(_ + _)

more 'relaxed' version

1 to 10 map(_ + 2) reduce(_ + _) view raw noddy-scala.sc hosted with ❤ by GitHub?

The irony is that once you’ve gotten past this initial hurdle, s-expressions lay the foundation that make Clojure one of the simplest and most consistent modern programming languages to use. But it does take some effort. Not loads. But it is something you have to push past. " -- http://owenrh.me.uk/blog/2015/08/24/

---

let me summarize that again because imo it's important:

(reduce + (map (comp inc inc) (range 1 11))) vs (1 to 10).map(_ + 2).reduce(_ + _)

the first is clojure and the second is scala. the important parts of the second one imo are:

---

i used to have

X is a pronoun that acts like a lowercase identifier, but implicitly transforms its containing explicit block into an anonymous function taking a single argument, 'X':

{X > 0} == {x $ x > 0}

Y is like X, but Y may only be used where X is being used; the (possibly ancestral) anonymous function where X is being used is expanded to take 2 arguments. E.g.:

{X > !{Y} == x y $ x > !{y}

but actually if we have scala's way of doing (_ + _) == lambda x,y: plus(x,y), then the only time we need the above is when we want to repeat one of the anonymous arguments more than once in the lambda function, eg:

(X * X) == square == lambda x: x * x

so that's probably more rare. And if we have other variables, but only one of them needs to do this, then we use _s for the other and X for that one. And it's not too much to ask that when this doesn't work, the programmer has to actually write a lambda function.

So i'm releasing Y from duty here.

---

looking at the Scala stuff above, i'm not sure that "range" is special enough to get punctuation syntax like '...'.

btw do we want user-defined infix punctuation, or do we want to force everyone to just 'infixify' alphanumeric identifiers? i'm thinking we want user-defined, but make a simple rule to make it easy to tell at a glance which punctuation is user defined. This can go hand-in-hand with the precedence rules.

if 'range' is not '...', should probably give it a OneLetter?. I've provisionally given it 'B'.

---

mb a class of operators like Haskell's '>>'?

http://hackage.haskell.org/package/base-4.8.1.0/docs/Prelude.html#v:-62--62-

---

 drobilla 218 days ago | parent

I'm very happy to see Rust stabilize, about time we get a systems(ish) programming language with a half decent type system. With that said... I need to get some bikeshedding off my chest:

I hate to let such a triviality lower my enthusiasm for a language so much, but I just can not get over that awful inconsistent closure syntax :/

I don't get it. Most everything else has a nice unique keyword syntax, fn uses (args, in, parenthesis), proc syntax made consistent sense, then lambda is this crazy

linenoise thing that doesn't fit in at all. The "borrow the good ideas from other languages" approach has resulted in a great language, but "cram random syntax from other languages that doesn't fit" doesn't work out so well.

pcwalton 218 days ago

The natural thing to want in a C-like syntax is the "arrow function" closure syntax (like ES6 or C#), but that required too much lookahead to parse. Having a keyword discourages functional style, which would be a shame in a language with a powerful iterator library. So Rust went with the Ruby/Smalltalk-style bars, which are nice, concise, and easy to parse.


http://bytes.com/topic/python/answers/470920-recursive-map-nested-list presents an interesting way that Python's boolean tests semantics can be used for concise conditional logic:

def recur_map2(fun, data): if hasattr(data, "__iter__"): return [recur_map2(fun, elem) for elem in data] else: return fun(data)

is equivalent to:

def recur_map(f, data): return [ not hasattr(x, "__iter__") and f(x) or recur_map(f, x) for x in data ]

---

http://bytes.com/topic/python/answers/470920-recursive-map-nested-list shows me that if you publicly post unindented python code eg:

def recur_map2(fun, data): if hasattr(data, "__iter__"): return [recur_map2(fun, elem) for elem in data] else: return fun(data)

then you can just copy/paste that into ipython repl (but not Python repl) and it will work (eg indent correctly)

still dont think that's enough to permit whitespace layout syntax for oot, b/c if you copy/paste from an ordinary, indented Python text file (esp if in the middle of stuff), it often wont work imo; eg the non-indentation of the above takes special work for the poster

---

you really want to have strings, associative arrays, and dynamically-sized arrays or lists. you want to have literals for all of these.

a common task is to input/output a string to a function. if you can't do this directly, that's annoying.

these literals should permit dynamic values (eg Metatrader has arrays and array literals but does not support dynamic array literals, eg 'int a[] = {3,1,2};' is okay but 'int x = 3; int a[] = {3,1,x};' yields error 'constant expression required').

if you don't have dynamic list literals, then unless you support variadic functions, it's cumbersome to use things like a variadic "min" function. You can write a "min" function that takes a list of variable size as input, but without dynamic list literals, it's a pain to do something like: 'min([f(), g(), h()])'.

---

to make common type annotation easy, eg should be able to type Int as a shortcut for ^int

---

on the need for a matrix multiplication operator (or at least custom infix operators):

x0x0 203 days ago

I well understand R's operators, but why on earth is that relevant?

math:

   S = ( H β − r )^T * ( H V H^T )^{-1} * ( H β − r )

python, ugly mess

   S = (H.dot(beta) - r).T.dot(inv(H.dot(V).dot(H.T))).dot(H.dot(beta) - r)

python, better: (although @ is an ugly matrix operator)

   S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

the latter is an order of magnitude easier to understand, and looks just like the math. Having one layer of indirection: math to code, is far better than two: math to code to obfuscated code because you won't create infix operators.

Edit: examples stolen from the matrix operator pep

---

problems if core language stuff can be redefined:

a_bonobo 304 days ago

You can cause some mischief - if you write a package, or distribute a .Rprofile to colleagues, you can hide somewhere in there a

temp <- F

F <- T

T <- temp

and if your colleagues are lazy and use T and F (instead of TRUE and FALSE) fun and very gnarly to debug things are going to happen!

Nichts ist wahr! Alles ist erlaubt!

hadley 303 days ago

There are way worse things you can do than that! e.g.

`(` <- function(x) { if (is.numeric(x) && runif(1) < 0.1) { x * 1.1 } else { x } }

;)

---

yknow, as much as it adds complexity, it really is nice how in python you can write a/2 + 7 < 3 - y and b - c > 3 + d and e in f

and the 'and's take lower precedence

---

someone arguing in favor of coffeescript: "Implicit hashes make for easy keyword-based arguments, only requiring '->' to make a value lazy is a bit better than () =>, and in particular not needing to end a big block of mixed code and data in a random mix of ")}]});" is a surprisingly big win, aesthetically."

---

arg: https://github.com/reinderien/mimic (unicode homograph code)

---

in Python, it's annoying that

object.fieldname

is a different syntax from dictionary['fieldname']

they should probably both be both (object.fieldname for when the fieldname is fixed, or dictionary[dynamic_fieldname] for when it's a variable)

---

 harryf 5 hours ago

What makes me snarky is the replacing of

    '%s %s' % ('one', 'two')

With

    '%s %s'.format('one', 'two')

The latter is just more annoying to type. Stupid argument I know but I find myself grumbling to myself every time...

reply

RussianCow? 5 hours ago

The second example should be:

    '{} {}'.format('one', 'two')

Either way, the former example still works in Python 3.5, so that syntax hasn't gone away. `format` is preferred, though. This Stack Overflow question has some good answers as to why: http://stackoverflow.com/questions/5082452/python-string-for...

reply

mixmastamyk 4 hours ago

Simplified to this in Py 3.6:

    f'{one} {two}'

reply

---

https://bugs.ruby-lang.org/issues/11537

" I sometimes write following code with rails application:

u = User.find(id) if u && u.profile && u.profile.thumbnails && u.profiles.thumbnails.large ...

or

  1. Use ActiveSupport? if u.try!(:profile).try!(:thumbnails).try!(:large) ...

I hope to write shortly above code. Groovy has above operator named "Safe navigation operator" with "?." syntax. Ruby can't use "?." operator.

Can we use ".?" syntax. like this:

u = User.find(id) u.?profile.?thumbnails.?large "

i think they eventually settled on &. instead of .? b/c eg

"u&.profile reminds us as short form of u && u.profile."

---

Perl6's comments:

  1. `( Multiline comments use #` and a quoting construct. (), [], {}, 「」, etc, will work. )

---

smalltalk has an interesting 'syntax' for conditionals:

condition ifTrue: [body] ifFalse: [body2]

what is happening is that 'condition' evaluates to either True or False, and then an 'ifTrue' message is sent to that True or False; True and False respond to the ifTrue and ifFalse message by executing/ignoring the content as appropriate. The content is a block containing the body of the conditional.

what is interesting is that this is not 'syntax' at all, just ordinary message passing.

could this handle 'truthiness'? well if you treated 'message passing' as objects with a 'self' first argument, like Python, then sure; you could use something like type classes to allow truthy behavior to be added onto another type by a third party (by defining how the ifTrue and ifFalse functions worked on that type); or if everything derives from Object, like smalltalk, you could still put a coercion to bool in the body of Object's functions ifTrue and ifFalse. But if you used the smalltalk system where they are really just message passing, not function calls with an implict argument, and if everything didnt derive from Object, then i think you could have truthiness only when built-in by creators of new types (by defining responses to messages ifTrue and ifFalse) but not added by third parties.

---

smalltalk seems to use '^' instead of 'return'

smalltalk uses [] instead of {} for blocks

smalltalk seems to use key:value for keyword arguments

smalltalk uses spaces for attribute access, which is actually sending messages, eg 'self dependents' is what in other languages would be 'self.dependents', and means sending the 'dependents' message to 'self'

smalltalk uses ~~ for ~=

smalltalk uses #literal for keywords (in the Ruby sense)

---

could use "!" prefix to indicate "do it now!", and reorder other commands

and could use "!" alone on a line to indicate a reordering barrier

reordered (non-!-prefixed) commands can then be reordered anywhere within the region delimited by reordering barriers, except that any reordering must satisfy data dependencies. are there implicit reordering barriers at function boundaries, or are reorderable statements within a function free to be reordered with other statements at its call site? and if so, should implicit reordering barriers also be at basic block boundaries within functions, and lexical scope boundaries within functions, eg for loops?

---

javascript apparently has !! which may mean 'is this null?', eg !!x seems to mean (x == null)

---

mb we should have a punctuation prefix, such as '^', which doesn't mean anything in particular but just means 'this operator is some sort of metaprogrammy thing'. so if the reader sees eg ^^, ^*, ^., etc, they immediately know they are dealing with black magic

---

"I would strongly recommend to anyone considering designing a new language at the present time: The sequence \n``` is utterly reserved and I will come down on you like a ton of tiny Internet bricks if you tamper with that convention. I suspect the present dominance of github is sufficient motive to keep it real. "

---

 frou_dh 228 days ago | parent

I think even in HolyC? you'll be fully quoting all paths. With general purpose languages, they're going to need either a recognised-shorthand-expanding preprocessor, or unfettered "reader" macros to be able approach Bourne shell style unadorned text that does process and file wrangling.

---

" My only wish would be that Erlang adopted Elixir's atom syntax, or that Elixir adopted Erlang's variable syntax, because then I could look at my code and know immediately at a glance what was a function, what was a Variable, and what was an :atom.

As it stands in Erlang atoms and functions look superficially the same, and in Elixir the functions and variables look the same. "

"

rvirding 4 hours ago

Just want to point out that atoms and function names ARE the same in that function names are atoms, they must be in fact as that what the system demands. So are module names for that matter. That is why if you want a function with a "funny" name you quote it as you do an atom

'the answer'() -> 42.

reply "

---

hoon uses a.b.c as a path literal

mb we should use a..b..c then to get a reified edge you'd have to make a Singleton list then index into it: a..b[0]

---

quoting could be provided by {}s. Inside a [] environment, where spaces are separators and {} is needed to switch back to code context, {{}} could be quoted code.

---

Hoon's "Lark syntax" [1] is only for binary trees so not too useful to use. But we should generalize it to my "(sorta)lattice graphs" where each edge from a node is colored with a small number of distinct 'directions'.

---

Hoon's mutation (search-and-replace) operator [2] is great; key aspects:

---

some comments on this tutorial part for Hoon's syntax (in terms of which parts we want to adopt for oot): [3]

---

some more comments on this tutorial part for Hoon's syntax (in terms of which parts we want to adopt for oot): [4]

a somewhat interesting ramble trying to justify the line noise:

" The philosophical case for a metalhead language is threefold. One, human beings are much better at associating meaning with symbols than they think they are. Two, a programming language is a professional tool and not a plastic beach shovel.

    "There's a guitar player, a harp player, a double-bass player, all holding up their blisters. Imagine if you downloaded a library off the internet... and it gave you blisters! Right? The horror! And yet... every musician has overcome a barrier to entry similar to this." — Rich Hickey

And three, the alternative to heavy metal is keywords. When you use a keyword language, not only are you forcing the programmer to tiptoe around a ridiculous maze of reserved words. You're expressing your program through two translation steps: symbol->English and English->computation.

When you shred, you are going direct: symbol->computation. A pure-functional language with syntax on the metalhead principle creates a sense of "seeing the function" which no keyword language can quite duplicate. Also, all the words you see on the screen are actually meaningful terms in the program.

But a great metalhead language should not be user-extensible. That way lies King Crimson. (Maybe Haskell is King Crimson: the prog-rock of programming languages.) A language is a standard; if users can do whatever with ASCII, there is no standard. If a metal language can work, it's only by rigorous consistency and predictability. No macros, operator overloading, etc, etc. "

this sounds reasonable and i tend to agree with it's leaning (that ideally a language prioritizes readability for someone who has already learned the language over not making beginners memorize anything at all; and that ideally a language has no alphabetic keywords; and that user-extensible punctuation grammar like Haskell has is bad) but disagree with the result. So i think this shows me that this decision is one of those kinds of design decisions where there is not just a principled rule to be discovered followed, but rather, each choice has costs and benefits and going to the extreme in either direction leads you to outcomes that have such high costs that they do not justify the benefits. And i think that Hoon has overshot here because even after spending a bit of time learning it, most of it looks like line noise to me.

so i think Oot needs to do three things differently:

and i think as far as not allowing user-extensible punctuation like Haskell, i think all we really need is two things:

---

some more comments on this tutorial part for Hoon's syntax (in terms of which parts we want to adopt for oot): [5]

tall and wide twigs:

i haven't used Hoon enough to see how it really plays out, but it's an interesting idea. To quote the tutorial,

" The very elegance of functional languages creates a visual problem that imperative languages lack. An imperative language has distinct statements (with side effects) and (usually pure) expressions; it's natural that in most well-formatted code, statements flow vertically down the screen, and expressions grow horizontally across this. This interplay creates a natural and relaxing shape on your screen.

In a functional language, there's no difference. The trivial functional syntax is Lisp's, which has two major problems. One: piles of expression terminators build up at the bottom of complex functions. Two: the natural shape of code is diagonal. The more complex a function, the more it wants to besiege the right margin. The children of a node have to start to the right of its parent, so the right margin bounds the tree depth.

Hoon does not completely solve these problems, but alleviates them. In Hoon, there are actually two regular syntax forms for most twig cases: "tall" and "wide" form. Tall twigs can contain wide twigs, but not vice versa, so the visual shape of a program is very like that of a statements-and-expressions language.

Also, in tall mode, most runes don't need terminators. Take =+, for example. Since the parser knows to expect exactly two twigs after the =+ rune, it doesn't need any extra syntax to tell it that it's done. ... The tall syntax...: the rune, at least two spaces or one newline, the first subtwig, at least two spaces or one newline, the second subtwig. Again, tall subtwigs can be tall or wide; wide subtwigs have to be wide. "

examples:

wide form: =+(planet=%world [%hello planet])

tall form:
=+  planet=%world
[%hello planet]

Additionally, not syntax but convention there is 'backstep indentation' style, eg:

?:  =(%world planet)
  [%hello planet]
[%goodbye planet]

Can tall forms nest within other tall forms? i'm not sure, but i think so (because [6] says that the point of 'backstep' indentation is to 'defend the right margin' and says this is like 'tail calls for syntax', which only makes sense to me if the last, unindented sub-expression contains other tall expressions).

I think there are some runes with irregular wide forms ([7] mentions this but .

'==' is used to terminate variadic tall runes (runes that take variable numbers of arguments)

My immediate objections to tall/wide syntax are:

Answers to these objections include:

Overall i'm torn. I do find it nice to not have so much indentation, but on the other hand:

So in the end i'm opposed to it.

---

must make it easy to compose readable regexes from parts

also "Whenever I’m debugging regular expressions, I miss /x from Perl, which lets you add insignificant whitespace and comments to regular expressions."

---