briancr

Joined 3 years ago

Karma
29
Submissions
25
Member since
Nov 11
Computational bioscientist
View on Hacker News

Recent submissions

Comment · 9 months ago
Yes, multithreading seems to be a consistent theme among the comments.. so I should definitely look into that. Thanks for the comment. (I actually haven’t done much threaded programming myself so this would be a learning experience for me..)
Comment · 9 months ago
Yes and the simplicity extends to function definitions too, since you don’t have to specify any type info. E.g.

f :: { ; print(args) }

Brevity is especially nice for inline/anonymous functions.

You can definitely use args.num, args.type[], and args.indices[] to figure out which optional parameters were passed, but I’ve decided that it’s usually easier to pass a full set of parameters into C and have the scripted wrapper handle the optional params. This is easy in Cicada because of ‘code substitution’ (one of the innovations I’m proudest of and if you’ve seen this elsewhere please let me know!). Example:

callC :: {

    mandatoryArgs :: { int, int }

    optionalArgs :: { str :: string; str = “default” }

    code

    mandatoryArgs = args

    optionalArgs(), (optionalArgs<<args)()    | set default, then allow user to change it

    $Cfunction(mandatoryArgs, optionalArgs)
}

Then you can call it with or without modifying the optional parameters from their default values.

callC(2, 3) | uses the default string

callC(2, 3; str = “modified param”)

callC() runs its arguments as a function, substituted into the params variable, allowing the arguments to modify params. This is weird and I haven’t seen it elsewhere, but it’s very useful.

Comment · 9 months ago
“IMO it's pointless to distinguish syntactically between iterating forwards and backwards” — I completely agree. It’s really a compiler-macro limitation that’s preventing me from doing this.. though I don’t have to go that route.

I think what you’re suggesting would require the <a, b> syntax to produce a proper iterator type, which it doesn’t currently do. That’s definitely worth considering — then you could attach methods, etc.

Thanks for the suggestion! I’ll think about the best way to fix this..

Comment · 9 months ago
Also, if someone else has access to the member, meaning that there is an alias to the member, then the reference count should reflect that. Here’s an example:

i :: int | 1 reference

a := @i | 2 references

remove i | 1 reference

The data originally allocated for ‘i’ should persist because its reference count hasn’t hit zero yet.

Comment · 9 months ago
No, there are both referenced-based and tracing-based GC routines that will deallocate short-lived objects. Sorry, I was just trying to enumerate the ways memory goes out of scope to show that none of those ways results in an invalid pointer _within the scripting language_.

The safety comes because there is no way to access a pointer address within the scripting language. The main functionality of pointers is replaced by aliases (e.g. a = @b.c, a = @array[2], etc.). The only use of pointers is behind the scenes, e.g. when you write ‘b.c’ there is of course pointer arithmetic behind the scenes to find the data in member ‘b’.

Having said that, it is certainly possible for a C callback routine to store an internal pointer, then on a second callback try to use that pointer after it has fallen out of scope. This is the only use-after-free I can imagine.

Comment · 9 months ago
Seconded.
Comment · 9 months ago
Yes very C-like.. One immediate difference is that in these C-like scripting languages there’s a split between definitions and executable commands. In Cicada there are only executable commands: definitions are done using a define operator. (That’s because everything is on the heap; Cicada functions don’t have access to the stack). I personally think the latter method makes more sense for command-line interactivity, but that’s a matter of taste.
Comment · 9 months ago
Yes I like this one. It’s similar and even more C-like, in that it discriminates between classes, class instances, functions, methods vs constructors, etc. (Cicada does not).
Comment · 9 months ago
This one’s Brood VI!
Comment · 9 months ago
Very cool! I’ve never used Kotlin..
Comment · 9 months ago
There’s no multithreading so race conditions don’t apply. That simplifies things quite a bit.

There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, and in no case is there any dangling ‘pointer’ (member or alias) pointing to unallocated memory. Does this answer your question?

I agree that my earlier statement wasn’t quite a complete explanation.

Of course, since it interfaces with C, it’s easy to overwrite memory in the callback functions.

Comment · 9 months ago
Yes there are lots of runtime checks.. unfortunately, but I always fork the time-consuming calculations into C anyway so those checks don’t really affect overall performance much.

Scripted functions have no set arity, and the same applies to callback C functions. Scripted functions collect their arguments inside an ‘args’ variable. Likewise, each C function has a single ‘argsType’ argument which collects the argument pointers & type info, and there are macros to help unpack them but if you want to do the unpacking manually then the function can be called variadically:

ccInt myCfunction(argsType args)

{ for (int a = 0; a < args.num; a++) printf(“%p\n”, args.p[a]); return 0; }

So all functions are automatically variadic.

It’s good to know that these GC/etc. solutions are even used by the big languages..

Comment · 9 months ago
Yeah this is why the syntax is customizable.. maybe it’s not optimal.

The example I gave was strange and I’ll have to change it. Not sure what I was trying to show there. The basic syntax is just:

for counter in <1, 5> print(counter)

backfor counter in <1, 5> print(counter)

It’s not overloaded because ‘for’ is basically a macro, expanding to ‘iterate, increment counter, break on counter > 5’ where ‘>’ is hard-coded. If ‘for’ was a fundamental operator then yes, there would be a step option and it would be factored into the exit condition.

You’ve got me thinking, there’s probably a way to overload it even as a macro.. hmmm…

Comment · 9 months ago
I know, I was dismayed to find out that there’s even another scripting language called Cicada.

The name came when I was living in Seattle and missed the sounds of east coast summer..

Comment · 9 months ago
There’s no multithreading capability built into Cicada. So a given instance of the interpreter only has a single concurrent state, and all C callbacks share memory with that global state. Multithreading would require a C-based thread manager.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton