Arc Forumnew | comments | leaders | submitlogin
2 points by evanrmurphy 5155 days ago | link | parent

I'm sometimes bothered by ! as well.

There is a certain sense to the way . and ! work now though. The dot in another context is used to notate the cons pair, as in (a . b) The ssyntax a.b expands to (a b), which isn't much different from (a . b) That's sort of fuzzy logic, I'll admit.

What isn't fuzzy logic is that a!b is equivalent to a.b if you could quote the b, as in a.'b Now you can probably see that the exclamation point ! happens to look like .' if you could superimpose the two characters. (Perhaps you already knew this.)

I might actually be with you on granting . the present meaning of ! I'm not sure the form (a b) needs a ssyntax, but it's really handy to have one for (a 'b) since table references are so common. I prefer scheme's use of ! and ? at the end of function names to signifcy destructiveness and predication, respectively. (For example, set! and number?)

Update: How about the vertical bar "|" to take the place of dot? a|b could expand to (a b) and a.b to (a 'b).



1 point by Pauan 5155 days ago | link

That sounds okay, but I'm not convinced we should even have a syntax for (x y). When reading other people's code that uses that syntax, I felt like it would be clearer and easier to read if they had used normal parentheses.

I do think that ":" and "!" are big wins, though (even more so if "!" is changed to ".")

-----

1 point by akkartik 5155 days ago | link

In readwarp.com I have a data structure with hash tables nested several levels deep, which I access using things like userinfo.user!stations.station!read-list.doc!title. That's much more of a mouthful without ssyntax.

I'd say I use . about as much as I use !.

-----

1 point by evanrmurphy 5155 days ago | link

Just experimenting with the alternatives using your example...

1. Original:

  userinfo.user!stations.station!read-list.doc!title
2. With '.' instead of '!' and no substitute for the original '.' :

  (.title ((.read-list ((.stations (userinfo user)) station)) doc))
3. With '|' instead of '.' and '.' instead of '!' :

  userinfo|user.stations|station.read-list|doc.title
#1 actually looks suprisingly readable to me right now. I guess I've grown more accustomed to '!' than I knew. ^_^

---

Update: What about '>' ?

  userinfo>user.stations>station.read-list>doc.title

-----

1 point by rocketnia 5155 days ago | link

I've considered > too, but I keep wanting to use < and > in names, like for XML, comparators, and very special-purpose conversions (a->b). Conversions can live without it, but I don't know about comparators and XML.

Another idea is /. Arc uses / in variable names, but I can't help but think that 'w-stdout would be just as iconic as 'w/stdout. There could be some potential. ^_^

-----

1 point by akkartik 5155 days ago | link

Depending on the font '|' extends too high and low, and seems a bit too heavy a divider.

Also, thaddeus pointed out that lisp readers use || to delineate symbols, so this may be hard to change in arc.

-----

1 point by evanrmurphy 5155 days ago | link

> userinfo.user!stations.station!read-list.doc!title

If arc had a macro for chaining "!" forms (I'll call it "!!" here), then this example could be nicely expressed without so much ssyntax:

  (!! (userinfo user) (stations station) (read-list doc) title)
Switch "!" to "." and now you've joined Clojure and LavaScript: ^_^

  (.. (userinfo user) (stations station) (read-list doc) title)

-----

2 points by akkartik 5155 days ago | link

Could we get rid of the ./! distinction by having it check if the second operand is bound?

  (. userinfo user stations station read-list doc title)

-----

3 points by evanrmurphy 5155 days ago | link

I think you're onto something!

This would mean that (h k) in table access would sometimes be synonymous with (h k). If k is bound, look up the value of k, else look up the symbol k. If k is ever bound but you actually wanted to pass in the symbol, you can still use (h 'k).

---

Since this all boils down to entities in functional position, why not take it a step further: auto-quote [1] all unbound symbols, the ones most relevant to this discussion being those passed as arguments to functional position entities, including functions, lists, tables and strings.

Ramifications:

  > (def f(x) (list 1 2 x))
  #<procedure: f>

  > (f x)
  (1 2 x)
  > f.x
  (1 2 x)
  > (= x 3)
  3
  > (f x)
  (1 2 3)
  > f.x
  (1 2 3)
  > f.x.0
  1

  > f.h
  (1 2 h)
  > (= h (obj k1 'v1 k2 'v2))  ; [2]
  #hash((k1 . v1) (k2 . v2))
  > f.h
  (1 2 #hash((k1 . v1) (k2 . v2)))
  > f.h.2
  #hash((k1 . v1) (k2 . v2))
  > f.h.2.k1
  v1
I like this...

---

[1] Perhaps another way to think about this, instead of in terms of quotation, is that all symbols are initially bound to themselves. (Note that this plays nicely with t and nil.)

[2] Actually, by the same principle this could be written:

  (= h (obj k1 v1 k2 v2))
You don't need to quote v1 and v2 because they're unbound in the enclosing environment.

-----

1 point by Pauan 5155 days ago | link

I really like the idea of combining the two. It seems like there's such a small distinction between them that they really serve a similar purpose. This would also solve all the problems with discussions about alternate syntaxes, since there would be a single syntax for both.

Crazy idea, having symbols bound to themselves by default. I wonder if that would cause any problems, though... sounds like an interesting idea to experiment with.

-----

1 point by evanrmurphy 5155 days ago | link

No responses yet, eh? I should have known that the incredible glory of this idea would leave you all speechless. XD

Here's another thing it gives you for free, super convenient alist initialization:

  > (x.1 y.2)
  ((x 1) (y 2))
  > (= a that)
  ((x 1) (y 2))
  > (alref a x)
  1
And then, with a variation on http://awwx.ws/alistcall, you get super convenient alist lookups too:

  > a.x
  1

-----

2 points by akkartik 5155 days ago | link

Patience, I was trying to make wart autoquote :) The obvious place to start is just call with one arg, but I am stumped trying to make this test pass:

  (test "call on one arg autoquotes"
    :valueof (call 'idfn xxzx)
    :should be 'xxzx)
It's the old problem with wart: there's no way to check if a variable has a lexical binding.

Hmm, I wonder if I should shoot for the moon and find the right handler to install for the UNBOUND-VARIABLE condition..

Update: I'm tantalizingly close, but perhaps it's not possible. This page outlines how: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node322.html

But I'm concerned by the phrase, "If this [restart clause] were part of the implementation of symbol-value.." Does that mean it isn't possible?

If we can do this we can also handle 'undefined-function and turn wart into a lisp-1!

-----

1 point by evanrmurphy 5155 days ago | link

Oh I see. You're actually doing something instead of just sitting here yappin' about possibilities. Delay excused then. XD

-----

1 point by Pauan 5155 days ago | link

Fair enough, though I still think they should at least be swapped.

-----

1 point by rocketnia 5155 days ago | link

Even if Arc were supposed to be like other languages (a kinda dubious goal), a.b probably wouldn't mean field-getting, string concatenation (PHP), and function composition (Haskell) all at once. As it is, it's already closer to field-getting than either of those other things; for lists, x.9 is like getting a field named "9", while cadr.x is like getting a field named "cadr".

I actually think cadr.x is a better way to go for field-getting. If the language has good enough namespacing support, variable names are automatically more malleable than specific symbols. If anything, we could just rephrase it as x.cadr. The trouble is that refactoring x.func into (func x y) is even more work; there'd be a demand for an x.func(y) syntax. Not that that would be a bad idea, just a more complicated one. ^_^

(I originally brought up the similar idea of an a'b => (b a) ssyntax at http://arclanguage.org/item?id=13061 .)

Backing up, let's suppose Arc doesn't need to be like other languages. The current meaning of a.b fits my needs pretty well. I use (a b) significantly more often than (a 'b), partly because I tag my types using 'annotate; even if one of my types is represented by an "a!b"-friendly hash table, I access it using "rep.x!field-name", meaning I use one '.' for every '!'. (BTW, do you think ((rep x) 'field-name) would be clearer?)

Since (a b) is so common for me, I like that it uses one of the conveniently un-shifted punctuation characters (on an American keyboard):

  ;,/.'

-----

2 points by Pauan 5154 days ago | link

While I was reading your post again, I realized that "," would also work, though I'm not sure we want to use such a nice character, or save it for something else. I also like the a'b syntax, so there's definitely plenty of options to consider. It's more a matter of deciding whether things should change, and if so, in what way.

P.S. to directly answer your question, yes I think that would be clearer, though more verbose. It's a bit hard for me to pick out the individual elements, because they're all squished together due to the infix syntax.

My current view of the various styles:

  (foo rep/x.field-name)       ; good
  
  (foo rep|x.field-name)       ; undecided; looks pretty weird
  
  (foo rep'x.field-name)       ; tied for favorite

  (foo rep,x.field-name)       ; tied for favorite
  
  (foo rep.x.field-name)       ; okay, but too hard to see the "."s

  (foo rep.x!field-name)       ; don't like the !

  (foo (rep x).field-name)     ; doesn't look lispy enough

  (foo (rep.x 'field-name))    ; good: very lispy, but not too verbose

  (foo ((rep x) 'field-name))  ; too verbose
I actually really like the foo,bar syntax for (foo bar). Especially when considering that the only difference between . and ! is that ! quotes the symbol, so it makes sense that the two would look very similar, right? Also consider this:

  (something foo,bar,qux)

  (foo,bar,qux.corge)

-----

1 point by Pauan 5155 days ago | link

I think it depends on the semantics of the situation. I don't like seeing things like "car.a" or "car.cdr.car.a" because I know that car and cdr are functions, so it kinda screws with my brain.

I feel like function calls should look like function calls, but when adding syntax, they should look different from non-function calls. According to that rule:

  (= foo (list 1 2 3))
  foo.2         ; good
  car.foo       ; bad

  (= foo (obj x 1 y 2))
  foo.x         ; good
  keys.foo      ; bad

  (= foo "bar")
  foo.0         ; good
  downcase.foo  ; bad
In other words, I'm okay with the . syntax when the first argument is a non-function. But I don't like seeing/using the . syntax when the first argument is a function.

For instance, the : syntax is used for functions only. I think the . syntax should be used for non-functions only. It just helps me to cognitively understand a program with the least amount of effort, but others may disagree.

I agree that Arc shouldn't especially try to be like other languages, but since the distinction between . and ! is mostly arbitrary, choosing a syntax that is more appealing to people coming from other languages is a nice bonus. Especially given that JavaScript is quite popular (for better or worse) and has some nice functional aspects to it (closures, lambdas, etc.) which make it conceptually similar to Scheme, even if the syntax is very different.

Note: if it were possible to combine the two without causing big problems (see evanrmurphy's post), then I might be okay with using the same syntax for both forms.

-----

3 points by evanrmurphy 5154 days ago | link

> I think it depends on the semantics of the situation. I don't like seeing things like "car.a" or "car.cdr.car.a" because I know that car and cdr are functions, so it kinda screws with my brain.

> I feel like function calls should look like function calls, but when adding syntax, they should look different from non-function calls.

One of the features of a language like Arc or Scheme (i.e. lisp-1's) or JavaScript is that functions are not treated especially differently from other data types.

Forget special syntax for a moment. In Arc we can call a function with (f x), a macro with (m x), access a list with (xs 0), a string with (s 0) and a table with (h k). We even call each of these, "putting the [function|macro|list|string|table] in functional position." So, even before ssyntax is introduced, Arc has taken pains to go against your wish of making function calls and non-function calls look distinct from one another.

Overloading functional position is very powerful once we do get to ssyntax because it allows us to overload that as well. Now all we have to do is introduce one syntactic convenience, a.b => (a b), and it becomes available to all the types.

If you like the syntax when it represents list, string or table access but not when it's a function or macro call, you could simply not use the syntax on functions and macros. So you have xs.0, s.0, and h.k, and you have (f x) and (m x). Otherwise, I'd consider that the root of your grievance may be that Arc overloads functional position for all these different types to begin with.

Do you think that could be the case?

-----

2 points by Pauan 5154 days ago | link

Actually, I like that Arc overloads so many things. I suspect the primary reason I dislike using . for functions is because of my JavaScript background. After years of programming in JavaScript, it's become very ingrained into me that . means "property access"

I agree that for my code it's a simple matter of not using the syntax in the areas that I don't like it. In fact, I don't need to use any syntax at all: I could use pure S-expressions if I wanted.

I guess what it comes down to is, "I want to use . for property access in tables, or at least use something that's not !" and although it looks weird to me to use . for function calls, I'll concede that Arc is not JavaScript, so I think I can tolerate it.

Thus, combining . and ! might be the best way. Alternatively, I think these would be very nice as well:

  x,y -> (x y)
  x.y -> (x 'y)
Or:

  x'y -> (x y)
  x.y -> (x 'y)
Or:

  x,y -> (x y)
  x'y -> (x 'y)

-----

1 point by thaddeus 5155 days ago | link

I can't help but to disagree.

The | is used for wrapping a symbol having spaces i.e. |my symbol|, and by having a vertical bar there it helps me remember I am referencing a symbol, not resolving a named variable.

When choosing between | and !, I'd rather have the exclamation mark.

-----

1 point by Pauan 5155 days ago | link

Note: I was referring to swapping the semantics of . and !

I don't care as much whether it's ! or / or | or whatever, but I feel like . is more natural for property accesses (keep in mind I'm coming from a JavaScript background, so I'm very used to using . in that way)

-----

2 points by thaddeus 5154 days ago | link

> I was referring to swapping the semantics of . and !

As was I, though I could have been clearer.

> I feel like . is more natural for property accesses

Fair enough. I will suggest, even though it's not natural relative to your experience, that the right path to follow on how things should work/behave in arc would be: #1. build on the current language constructs then #2. compare features from other languages and try to incorporate the best/better ones. When it comes to the question of "is language-x's implementation better than the current arc one?" I will suggest our personal preferences are secondary to building on existing arc/lisp constructs. Otherwise the language will get pulled in too many different directions and dependent upon the month (and whomever is comprising the guiding force of arc's evolution) we could find things changing back and forth - and that would be really bad.

-----