Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Language Syntax Discussion #14

Closed
mrkmarron opened this issue Apr 17, 2019 · 30 comments
Closed

Language Syntax Discussion #14

mrkmarron opened this issue Apr 17, 2019 · 30 comments
Labels
design discussion Language design discussion issue

Comments

@mrkmarron
Copy link
Contributor

There seem to be a number of comments thoughts on language syntax. This issue will consildate general thoughts and suggestions. Other more specific issues can be created and referenced from here.

@mrkmarron mrkmarron added the design discussion Language design discussion issue label Apr 17, 2019
@mrkmarron
Copy link
Contributor Author

The use of ~ presents problems issue #13

@merriam
Copy link

merriam commented Apr 17, 2019

You represent your language syntax plan as:

  1. Bosque code should be obvious and simple.
  2. Code should easy to reason about for both humans and computers.
  3. Requiring deep context is a language wart or 'pimple',
  4. We want immutable values, except when we mutate variables; this is just a 'dimple'.

There is some clarity needed to make the conflicting goals of threading and determinancy, easy reasoning and tagged typing. Looking at this, efficiency is explicitly not a goal?

If you are local to the Silicon Valley, this could be a fun lunch discussion.

@voronoipotato
Copy link

voronoipotato commented Apr 18, 2019

As a preface, I'm biased. I like F# and Fable quite a bit and these do affect my perceptions.

Syntax is honestly my biggest struggle with the language as implemented. It appears to borrow a lot from ML, but then the syntax feels awkwardly pulled from JavaScript. If it were closer to an ML syntax it wouldn't be onerous to port code from F# / OCaml / Haskell, but it's going to always be onerous to pull from JavaScript given that the paradigms are fundamentally different. There will be confusion regarding the scope of var because your var is actually closer to JavaScript's let which is of course what ML uses. Then your var! is closer to var in JavaScript. In my opinion, var! is too challenging to differentiate from var, given how different the constructs are. I hope at the very least at some point in the future we will have an ML syntax mode where you don't need to put { everywhere, which are in my opinion noisy and do not provide value. If the syntax looks like JavaScript we cannot expect the usage to be meaningfully different from JavaScript. People will paste and tweak code and it will be strictly less useful than good inter-op with existing JavaScript because the foundational paradigms of Bosque are meaningfully different from JavaScript.

My personal unsolicited syntax guidance

  • Avoid idiom for anything that isn't used constantly
    • they are hard to remember and turn away beginners
  • Avoid operators for things that aren't used constantly
    • they are hard to remember
    • operators have an ordering and reasoning and memorizing it is hard
    • you can add the |> operator to obviate most other operators
  • Try to consider not only the heritage of a syntactical pattern but also
    • how it serves the paradigm it exists in
    • how those patterns shape thought and expectations
    • if syntax you're porting from actually aligns with the intentions of your language
  • don't create a new syntax pattern if an existing pattern solves the problem. It makes porting harder, learning harder, and the language appear incomplete or not thought through.
    • fn(x) => x*x;
      • use fun x -> x*x;
      • or (x) => x*x;
    • var! , this introduces a few problems some of which I've addressed
      • suggestion, make this hard or ugly or you will see it all over every codebase
    • var meaning something immutable, something directly contrary to what var(iable) means
      • suggestion use let
    • javascript style function invocation means adding automatic currying could be painful
      • suggestion consider ML style function invocation
    • ; being the "empty" statement. Is this akin to unit () in ML?
      • suggestion use ()
    • <: why can't this be a function, and what do I call it
      • suggestion use a function
    • [ x, y ] for tuples is confusing both for ML and javascript people
      • suggestion use (x,y)
    • List@{1, 2, none, 4} is confusing for everyone
      • suggestion, use [1,2, none, 4] or List(1,2,none, 4)
    • Generic[T] is confusing for both ML, C#, and javascript people
      • suggestion, either use Generic<t> or more in line with postfix types t Generic

I'm biased, all of this could be useless to you but I hope I've at least illuminated why I've come to the biased conclusions I have. Thank you for your time and I hope your language is very successful.

@defunkydrummer
Copy link

Any language that wants to be modern, should either use s-expression syntax (Lisp, Scheme, etc) or ML(SML, OCaml, F#, Haskell) syntax. Anything else might be easier to learn to beginners accustomed to C/Js/Java, but ultimately a large hindrance for doing useful, non-trivial software in a way that advances the state of the art.

@mattferrin
Copy link

I would think that any text that can be streamed in a single forward pass is good text. Any text that allows an editor to show opening and closing of scope is good too.

@Ischca
Copy link

Ischca commented Apr 19, 2019

I don't want to enter a semicolon.

@pinggi
Copy link

pinggi commented Apr 20, 2019

Totally agree with @voronoipotato, the syntax is stupid. Why [] is used for generics and tuples and @{} for a new list ? Why fn() is used to denote a closure? fn suggests a function and functions don't capture variables. Rust has impl Fizz for Bar and Bosque offers entity Bar provides Fizz. The map function replaces for loop? I worry, this language doesn't bring anything new only confusion.

@mrkmarron
Copy link
Contributor Author

As a reminder this project operates under a code of conduct. Criticism and disagreement are welcome but we require all participants to communcate their views in a respectful and professional manner.

@merriam
Copy link

merriam commented Apr 20, 2019

Perhaps I misunderstand.

Calling syntax stupid, even insulting the work product of others, if a far cry from insulting others. Usually, criticism of work, imperative sentences ("change this to that...") are part of the normal course of communications. Most code of conducts try to prevent the ad hominem slide into popularity contests.

Do you feel the above conversations are beyond your code of conduct? What specifically would you change to keep the meaning and stay within your guidelines.

@voronoipotato
Copy link

voronoipotato commented Apr 22, 2019

When writing a post about syntax it's good to read your post for about 5 minutes before submitting. I think it's normal for people to have an emotional reaction to syntax. Syntax is deeply cultural. Syntax shapes thought. Syntax is hard to get right. However it's important when we feel and express our feelings, to explore what about the subject cultivates those emotions. I do think @pinggi is mostly correct, however I think his approach is at risk of calcifying the maintainer. Instead of expressing the thought "this is stupid" lets try to approach language like "This syntax is a problem for me for this reason" or "When the syntax is like this it makes me angry for this reason".

For example, "The syntax makes me angry because it denies its heritage, undermines the values that is seeks to adopt, and adopts the trappings of a language which actively works against its aims. This is a problem for me because when I use it I will always feel like I am fighting myself, and my existing code, whether I come from Javascript, C#, C++, C, F#, OCaml, or Haskell."

@xcaptain
Copy link

I prefer to omit parentheses for if statement, go/rust/OCaml does that

@orcmid
Copy link

orcmid commented Apr 29, 2019

As a preface, I'm biased. I like F# and Fable quite a bit and these do affect my perceptions.
Syntax is honestly my biggest struggle with the language as implemented. It appears to borrow a lot from ML, but then the syntax feels awkwardly pulled from JavaScript. If it were closer to an ML syntax it wouldn't be onerous to port code from F# / OCaml / Haskell, but it's going to always be onerous to pull from JavaScript given that the paradigms are fundamentally different. There will be confusion regarding the scope of var because your var is actually closer to JavaScript's let which is of course what ML uses.

This part resonates with me. The suggested details not so much :).

SML has this interesting way of allowing what looks like indentation-based few { ... } and ( ... ) layout that, if I understand it correctly, actually works off the reserved words and has a grammar and requires nothing of indentation, off-side rules, etc., and is easily reflowed and pretty-printed. That such can be machine-produced, successfully passed around in email and such, is very valuable in my thinking.

I dislike the use of ( ... ) for tuples and parameter lists (which may be a different kind of sugar in an applicative language), and favor the use of something like [t1, t2, ..., tn] for constructed tuples, whether homogenous or not. so f[a1, a2, ...] is different than f(a1, 12, ...). But that's me and I need to understand the grammar of Bosque better and not worry about my personal preferences in a language of my own making.

Begin Personal Soapbox

I confess to a preference that goes completely against the functional programming, lambda calculus, combinatory logic tradition (and I think Church had it right until he also went over to the dark side :). I am not lobbying for this, because it causes consternation when someone sees that the familiar form is seriously different than what is now thought "traditional."

Although it is great to have function first-classness, I think having "a b c x" be interpreted as "((a b) c) x" as applicative syntax is just screwy when we are normally operating on base types and often domain results that are not functional. So I cling to the semantics being the same as "a(b(c(x)))" and am very happy I can drop all of those (...). But then, I also accommodate a(b,c) x as shorthand for ((a b) c) x, etc., and writing the grammar for it is pretty easy. (Here I mean grammar, not parser specification.) If you are remotely curious, https://github.com/orcmid/miser/blob/master/oMiser/ob-exp.txt

I promise not to mention this again.

End Personal Soapbox

@orcmid
Copy link

orcmid commented Apr 29, 2019

@merriam, I don't think the objection to "stupid" was about anything you've said, at least not in a current edit. The problem, I think, is how this is taken as a reflection on the associated person. Like being in a review meeting and having Bill Gates say "That is the stupidest proposal I have ever seen."

One can argue that the proposer should not feel public humiliation. That is not very compassionate and, I daresay, also not very civil. One way to restate this sort of thing is to own one's own reaction and not attribute it elsewhere. Something like, "I am having difficulty seeing the merit of this. Please go back and look closer at how this is problematic. Discuss it with so-and-so." Or ask questions. Or request some 1-on-1 time. Whatever.

This should not be difficult. I grant there are cultural differences in this respect.

@voronoipotato
Copy link

My reasons for preferring ML syntax are primarily that they are fine and appear to be very close to the goals of Bosque. Any changes away from ML in this regard, be it OCaml, Haskell, or F#, should not be done with reckless abandon but rather deliberately and with some consternation. It's like if someone made a C-like language but randomly changed the syntax in ways that are not obviously better, and in some respects potentially worse at achieving the goals they hope to attain.

@orcmid
Copy link

orcmid commented May 1, 2019

@voronoipotato Although I am a card-carrying member of the "Next 700 Programming Languages School" (having been there when it was written and then presented), I only recently dug into ML, taking the first of a Coursera series on Programming Languages from the University of Washington.

I was stunned to see how many little problems just fall away with the coherence of the ML language structures and the conceptual integrity of it all, and I am making good use of SML in proof-of-concept work on a miniature (a.k.a toy) language of my own devising.

I think recursion, and mutual recursion, are handled just fine in SML and, in particular, it is natural in the sense that inscrutable errors are minimized and do not lead to hard-to-detect coding errors (such as omission of a rec in one place or another. (It is more difficult to refer to an outer entity of the same name as the function being defined, and fortunately, that is a tolerable thing to move to the edges.)

I think the SML handling of assignment operations, and of mutable entities, is pretty much a hack. At least it discourages over-use because of the smell. This is in contrast with var! in Bosque, and the prideful use of multiple/structural assignment. I am bemused that, in the case of var!, there is only "!" on the var declaration form and not any mentions (cf. rec). I can see other cases where a suffix "!" might be needed and I may have missed that in the language sketch du jour.

If there is a fascination on bulk actions, it might be useful to look deeper into APL and also Backus FP.

Also, there are ways to spit apart structures via pattern schemes. E.g.,

let (a, b, c) = some-composite-expressing-formulation
in ... body-exp

which allows (immutable) use of a, b, and c in body-exp.

The ML provisions for patterns and type inference seem to be something worthy of careful attention here, presumably without re-inventing F# but maybe not. It does mean that the language boils down to some coherent core with a straightforward sugaring for semantic expressivity.

Perhaps ML needs to be a benchmark case. How to also create powerful mutation cases while preserving the coherence and disciplined ability to reason about programs will certainly be challenging. I can only stand back and admire any resolution of that.

@voronoipotato
Copy link

I was hoping Bosque with its philosophy would make mutable entities a hack instead of a primary way of doing things :). Otherwise yes I agree.

@orcmid
Copy link

orcmid commented May 2, 2019

I was hoping Bosque with its philosophy would make mutable entities a hack instead of a primary way of doing things :). Otherwise yes I agree.

I see I wasn't clear. Yes, I am not happy about var! and making mutable entities so heavily appealing.

I would like something better than the SML hack, but have no idea how to accomplish it. Backus had the idea of moving mutation out of the functional language into a "system language" that would be a kind of wrapper environment where massive stuff happened, relying on pure functional stuff underneath. It would be great to find a happy middle.

There are safe kinds of assignment that are very appealing, and it would be nice to have that where it works great. I think what one wants to do is avoid assignment side-effects, aliasing issues, etc., just like we avoid the counterpart side-effect, goto.

My itch is to see if confined working sets (mutable over some lexically-scoped lifetime of a procedure-application instance) are meaningful. I am thinking of cases where tail-recursion is not improvement enough, such as modifying elements of an array or a component of a structure, maybe coupled with a meaningful copy-on-write underpinning.

I'm not certain whether this is a rathole crashing into the previously-unsolved problem no matter how one attempts to confine it. And I have no clue what the notational distinction would be and how one would do proofs and verifications, and keep people from going crazy over it. At this stage, I think I am blowing smoke out my ears and will have to be silent until there is something more constructive to demonstrate.

@Chris2011
Copy link

I would like to jump in here. My proposal is to use fun or fn for declaring a function. Afaik rust uses fn as the keyword for creating a function and kotlin uses fun. It is much more handy and "fun" to make it shorter instead of using the old function keyword. And another fact is, that it will make the code shorter. Of course, it depends on where the code will live in the future. My 2 cents.

@orcmid
Copy link

orcmid commented May 3, 2019

My proposal is to use fun or fn for declaring a function.

I am so accustomed to reading this kind of code that I overlooked the use of "function." "fun" matches the use of "var" (and let) being handy when lining up indentations too. I would avoid "fn" especially if a distinct keyword is needed for anonymous functions. Save it.

In general, shortened forms are useful to also remind folks that we are not necessarily talking about associated mathematical entities. That is the advantage of int, float, and fun over integer, real (yikes!), and function.

@orcmid
Copy link

orcmid commented May 3, 2019

OH OH

I am so keen about functional-programming and applicative languages, that I did not realize Bosque is not one of those. It is a block-structured ALGOL-like procedural language borrowing some C Language notational styles. That's already a handicap.

I take as evidence of too-much accidental complexity, section 6.5 Return and Yield in the Bosque Language Overview. There's more, but I think that section is indictment enough. I had expected too much and failed to dig deeper immediately.

@orcmid
Copy link

orcmid commented May 3, 2019

There are other ways to accomplish update (overview section 5.14) and preserve functional style. For example

structured-thing with a1 = e1, a2 = e2, ...

where the ai signify components of structured_thing that are altered in the result. Updating in place becomes a special form of assignment I suppose, like with= in harmony with += and such. Looking at this, I am uncertain whether one would tolerate some sort of this in the ei. Perhaps.

This idea is pretty old. Some time in the mid-1970s I wrote to Danny Bobrow asking if he knew of such an usage, and his paper-mail reply to me revealed some things about work at PARC that was not very public :). As far as I know this structure never caught on and I only recalled it reading section 5.14. This just solved a problem for me :).

Seems like a reduction in accidental complexity to me :)

@orcmid
Copy link

orcmid commented May 5, 2019

I want to call out the use of SafeStrings as a significant feature in practical operations. It is more of a language semantic concept than just syntax. It deals with a significant matter in the way ground objects are used to carry interpretations of higher-level entities. The paper linked from docs/papers/publist.md is very useful. Is there a publication of record that can be cited?

I suspect this is generalizable for situations where any kind of denumerable type is used as a substrate for encoding of something, conveyed as a type over the representation via encoding. Strings are a natural case, since latent type (great term) is so prevalent and so valuable in practice. Something like this would be very powerful in database systems where confusion of what columns represent with what the columns are is so prevalent.

I do wonder how nominal type and latent type relate, though. Could it be that the SafeString technique elevates latent type to nominal type?

@Chris2011
Copy link

Chris2011 commented May 5, 2019

Buzz word: Elvis Operator aka null coalescing operator to shorten null checks. https://en.m.wikipedia.org/wiki/Null_coalescing_operator would be nice If we can have it :)

@raphaelkieling
Copy link

raphaelkieling commented May 5, 2019

Pipeline operator like a elixir would be nice. Like data |> function1 |> function2

@mrkmarron
Copy link
Contributor Author

Hi, we have null coalescing -- see none chaining and none coalescing. Also working on pipelining for collection operations.

@Chris2011
Copy link

@mrkmarron thx :)

@khoshroomahdi
Copy link

Is there range operator?

@growlnx
Copy link

growlnx commented May 17, 2019

Hello Everyone!

I have some ideas to propose to the syntax of the forest language.

variable alias

sintax:

<var name> as <alias>

example:

x as y;

Int array initialization with a step description:

the numbers before the "..." will describe the step of progression,
if this sequence does not make sense, we give a semantic error message.

sintax:

[ <step description> ... <end> ]

example:

var arr1 = [ 1 ... 10 ]; // [ 1, 2, 3, 4, 5, 6, 7, 8 ,9, 10] 
var arr2 = [ 2, 4 ... 32 ] ; // [ 2, 4, 8, 16, 32 ]
var arr3 = [ 100, 50 ... 0 ]; // [100, 50, 25, 12 , 6, 3, 1, 0]

Using Lambda, for more complex initializations:

Using a sintax like haskell, but inside array backets.

sintax:

[ 
  <salt description> ... <end> as <alias>
  | <expr> <lambda>
  | [...]
  | otherwise <lambda>                                  
]

example:

var arr1 = [ 
  1 ... 10 as x 
  | isOdd(x) fn( x : Int) : Int => x++
  | otherwise fn( x : Int) : Int => x-- 
]; // [ 2, 1, 4, 3, 6, 5, 8, 7 ,10, 9] 

var arr2 = [ 
  1 ... 4 as x 
  | otherwise fn( x : Int) : Int => x*2 
] ; // [ 2, 4, 6, 8 ]

var arr3 = [ 100, 50 ... 0 ]; // [100, 50, 25, 12 , 6, 3, 1, 0]

String initialization

Like python, we can do something like this:

sintax:

 <size> * <string>

example:

var str = 5 * '.'  // '.....'

If combine ... this can be interesting.

var arr1 = 2 * [ 
  1 ... 5 as x 
  | isOdd(x) fn( x : Int) : Int => x++
  | otherwise fn( x : Int) : Int => x-- 
]; // [ 2, 1, 4, 5, 6, 2, 1, 4, 5, 6 ] 

@wanton7
Copy link

wanton7 commented May 31, 2019

Pipeline operator like a elixir would be nice. Like data |> function1 |> function2

Pipeline operator is awesome, but if/when it's implemented I would really like to have it support argument position where data is piped to. Like underscore is used in this language called Gleam https://gleam.run/tour/function.html

pub fn run() {
  // This is the same as add(add(add(1, 3), 6), 9)
  1
  |> add(_, 3)
  |> add(_, 6)
  |> add(_, 9)
}

@mrkmarron
Copy link
Contributor Author

Closing -- can reopen as needed with updated code

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
design discussion Language design discussion issue
Projects
None yet
Development

No branches or pull requests