Hacker News new | comments | show | ask | jobs | submit login
Show HN: Cixl – a minimal, decently typed scripting language (github.com)
64 points by sifoo 6 months ago | hide | past | web | favorite | 22 comments

I enjoy seeing new experimental languages. I really enjoyed working through the README exercises. It's the perfect way to document and teach a language all in one go. The REPL worked great.

First, I love how you've chosen to have functions wait for the correct number of arguments to exist on the stack before executing. I've often pondered how to make Forth-like languages less painful to program - your solution is very clever!

Speaking of clever, I felt very clever indeed when I took your infix equality example:

    | 42 == 42
and it worked when re-ordered as postfix:

    | 42 42 ==
...indicating two things: 1) I actually understood what was happening and 2) the language is coherent.

It's great that basic IO so simple with 'say' and 'ask'. That allows somebody to jump in immediately and start making fun things!

    | let name ask 'Who are you? ';
    say $name
Love the syntax for lambdas: { ... }

What is the rationale for requiring function implementations of the same name to have the same arity? Nevermind! I just answered my own question: because functions need to know how many parameters to seek from the stack.

The literal values for function arguments is awesome - pattern matching!

I don't understand this example demonstrating an "index" for the function parameter types:

    func: baz(x y Int z T0) $x + $y + $z;
I assume 'T0' is the aforementioned index? But I'm struggling to see how it works from this example. Maybe I'm just missing an idiom from some other language?

Bizarro Question: Is there any way you can 'delete' a function in the REPL? For example, to be able to re-use the name 'foo' as a function with a different arity. (It's fine if you can't. The ability would be useless in an actual program.)

You have an error in the README example for "Argument types may be specified in angle brackets...":

    | &+<Int>
  Error in row 1, col 6:
  Func imp not found
But at least I was able to guess the correct syntax, yay!:

   | &+<Int Int>
  [Fimp(+ Int Int)]
Dates: I'm confused about the lack of a function called 'year' (singular) since 'day' and 'month' exist. Otherwise, I'm impressed. Dates are damned hard.

Everything about this language seems to be aimed at maximum brevity without sacrificing clarity. I like that a lot. Congratulations for getting this far and I'll definitely be bookmarking this.

I would love to see some longer programs written in Cixl to get a sense for what they look like and how they'd be structured.

How long have you been working on this? How long have you been dreaming about it? And how it is pronounced (SIX-el, KIX-el)?

First of all, thanks for taking the time. I'll try to address your questions in the same order, feel free to yell if I miss anything.

'T0' will be substituted for the type of the first parameter (indexing starts from 0) on evaluation, it's the most straight forward way of adding the constraint that two parameters need to be the same type without specifying which type. I should make the example clearer by specifying a less concrete type for x.

Nope, no way right now. I realize it would be nice to have in the REPL but functions use their index in the list of implementations to implement upcall which means I have to figure out another way to do that fast for that to happen.

The reason some fields have plural functions as well is because they have dual semantics. You have both the total number of days and the specific day of month, for example. The year only has one meaning. I guess you could alias 'years' to 'year', but then someone is going to wonder why it's there instead. There's some more material on the reasoning behind dates/times in /devlog.

You pretty much nailed the heuristics I've been using to drive the design. It's been cooking for quite some time but I only started working on the implementation 3 weeks ago or so.

It's slowly getting to the point where it's possible to write more interesting code. I'm waiting for a couple of bigger pieces to fall in to place first, structs are up next.

The C in the name is derived from the host language, which would make that SIX-el.

Parameter types: Okay, I'm closer to understanding: "T0" means "Type number 0". But I'm still confused by the example:

    func: baz(x y Int z T0) $x + $y + $z;
z is the same type as the 0th type. I get that now.

But what's confusing me is that it looks as if x's type is unspecified. The 'Int' here belongs to y, right? I'm sure I'll slap my forehead when it's explained to me...

Dates: I see what you mean about there not being a "year of the _" semantically. But when formatting a date, I think of it as "year-month-day", not "years-month-day".

You've made excellent progress in 3 weeks! Keep it up!

Ok, now I get where you're going. x and y share the same type, just like 'int x, y' in C. That's what happens when you try to explain two concepts at the same time, my mistake. You have a point with the years, I'll add an alias for now. That is the goal; I'm kind of depending on people chipping in to be able to keep up the pace though, I had a nice runway set up for xmas but now the pressure is on again.

Param types: Ah, of course. I had a vague suspicion that was what was going on. But my brain was overloaded. Yeah, one concept per example is ideal. :-)

'Year' alias: excellent! That's one of those "look and feel" things that can make the transition to a new language so much smoother.

I was going to add something about "now comes the hard part after the initial flurry of activity: steadily growing the language without losing the passion." But I didn't want to end on a downer. I'm truly impressed with what you have so far.

Agreed, it needs momentum to keep going and that's where I could use some help right now. But it also becomes less of a struggle since I don't have to constantly invent the ground I'm walking on, and since it's now getting to the point where interesting programs are becoming possible. As an example, adding symbol support (https://github.com/basic-gongfu/cixl#symbols) took about 30mins.

It's a work in progress, but this is the longest piece of code so far. It's the start of a simple booking system.


Sweet, shades of FORTH. Very retro yet timely

The principles of Forth sit at the bottom of most languages, though most like to keep that power to themselves. And I've always felt that the Forth language suffered from being so damn dogmatic and protective about the obvious lack of convenience. As an added bonus, it makes a nice contrast to the current trend of crippling languages ever more to protect people from themselves.

Cool! Why'd you make it?

The fact that no one else was doing it started to feel like an obligation. Cixl is an attempt to find a middle way; a more permissive, less religious, yet modern and convenient approach to solving problems in code. Unlike most other languages; it isn't very interested in reinventing or ruling the world; and doesn't mind being embedded in and extended from other languages.

I was with you at first, but then your usage of semicolons went way overboard.

Which usage of semicolons are you referring to? The only one I can think of is using them to terminate definitions. I realize it's slightly unorthodox, like most of cixl; but many languages seem to be fine with using semicolons to terminate every single freaking statement, how is this worse?

I believe the semicolons in question are in your comment, not in your language.

Ah, epic swoosh :) They fill a clear purpose as a step between commas and periods, which allows putting more structure into sentences and helps express meaning more clearly. I've been told that they're more commonly taught and used in Europe than the US, and my first language was Swedish. On the other hand I definitely write more code than otherwise, so that probably explains some of my fascination with punctuation. In the end, languages are tools for accurately conveying meaning; (see, there he goes) and whatever rules don't contribute to that goal may safely be tossed out.

I tend to use semicolons only when writing about a series where some or all items in the series contain a comma or commas, thusly:

A semicolon has two general uses: to clarify a series and to indicate two closely related sentences.

Series — If one or more elements in a series contain a comma, use semicolons to separate them. Include a semicolon before the final conjunction. (Members of the Western Jazz Quartet are Tom Knific, bassist; Trent Kynaston, saxophonist; Steve Zegree, pianist; and Tim Froncek, drummer.)

Two closely related sentences — For the most part, you should use a semicolon only where you could also use a period, but want to demonstrate a relationship between two complete sentences. (Good grades are integral to student success; a strong support network is also important.)


Semicolons should be used to join two complete sentences while having a “comma-like” flow (e.g. “I like cake; it tastes good”). I personally tend to use them quite a lot (despite being American). However I generally don’t put more than one in a sentence, which I think is somewhat standard. That being said, I don’t think it’s considered an error, per se, to do so.

if you have a list where at least one element has a comma in it you should use the semicolon to separate the elements, like the sibling comment by spiceoflife says, so that would usually produce multiple semicolons in a single sentence.

Definitely. I meant that in the usage that I described (as a way to join complete sentences) you generally only see one per sentence.

The first semicolon doesn't appear to conform to any of the standard usages, nor does it seem to add any benefit over a normal comma. I thought the semicolon could replace a comma in a list of things, but you are using it to separate the intro clause? thing, like "In the end," above.

> and whatever rules don't contribute to that goal may safely be tossed out

Sure, but your usage here certainly isn't making things clearer.

"decently typed"?

Well, from one angle it's statically typed; names never change their types within a scope. It's also strongly typed, more so than common scripting languages. On the other hand it has a very dynamic, gradual feel to it; to the point where you almost don't notice. That and the fact that using the word 'decent' seem to upset a lot of people, which is an indicator of much needed mental debugging.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact