I’m working on an array programming language with a guy I met on Reddit. Not sure if he’s on here. I’ll be adding to the parser and maybe building a small type checker this week.
I occasionally write at https://bernsteinbear.com
Mostly PL stuff
I wrote a small paper for class on this, actually! https://bernsteinbear.com/dat-paper/
Good technical overview. Identifying WordPress (25% of WWW) as a potential for growth is an interesting suggestion.
Thanks! Glad you thought so. I figured it would be a good starting point since many WordPress blogs use minimal dynamic content that cannot be expressed as a static website.
You may already be aware of this but here’s an example about composability, especially with respect to editing parents. Its not primarily “for making UIs”.
The Alto & Squeak environments get close, and so does Tcl/Tk’s ‘wish’ interpreter, but we’re not there yet.
For each of these, which of your items are missing?
The beginning of some work along these lines is here: https://github.com/enkiv2/misc/tree/master/kamui
Can you post some screenshots and/or describe and discuss your current implementation, even if not final? It would help clarify some of your implicit assumptions about the problem and model. (For example, what are things you would consider a widget and not a widget.)
Every object has a visual representation.
Why only one? Or do you mean at least one?
Every visual representation corresponds to an object.
Also why only one? What about visually nested things? (Is a representation something already rendered or an abstract description?)
Edit: Also, can you post some links to some examples of UIs on TV you consider good examples of what you want to do?
For each of these, which of your items are missing?
I consider Smalltalk to have too high an initial learning overhead for this purpose (since my goal is to have the composability of graphical elements be an ‘invitation’ to programming in general for casual users).
Tk has a lower initial learning overhead but there are a lot of inconsistencies in how different widgets work (along with problems like a single-thread model), and no system has been written using Tk that does composability in the natural way smalltalk environments do. (I attempted a TCL/TK implementation many years ago. It’s briefly described here. It quickly became unmaintainable, and the widgets were not flexible enough for my liking.)
Can you […] describe and discuss your current implementation
Sure!
Io is an extremely simple homoiconic language with a prototype-based object system. It looks a lot like rebol. I chose it because an important part of making a language look understandable to non-programmers is conceptual simplicity, and Io’s pointfree style and message-passing-like behavior is a good fit for a context where a lot of the coding is glue between objects.
Because of certain features I wanted that stock Io didn’t have and certain behaviors that might be bugs (and because Io is not maintained), I decided to write my own implementation in a language with primitives that are a better match for the parts of Io I consider important for this task.
Since Io has a prototype-object system and not a class-object system, exploration through cloning a working object and modifying its guts is possible at run time. I expect this to be a normal pattern for experimentation.
I have defined the ‘widget’ object as having a position, size, and bitmap. Any widget inherits these properties. So, any widget has a visual representation, in the sense that it has a bitmap & that bitmap gets blitted to the display at render time. (Of course, it can be transparent, or whatever.) If you look at my implementation, I’ve also got some logic for visually nested things: children are positions at offset with respect to their parents, always at a higher layer, and their position affects the computed size of their parent.
The importance of widgets having a visual representation is that the expected method of modifying a widget is by selecting it in the interface and inspecting its implementation. So, ideally, every live object would be a widget whose visual representation indicates its state. (I don’t plan to make non-widget objects impossible, but it’s bad form, since they’re going to be harder to find and change.)
Unfortunately, I haven’t gotten to the point of having anything render. Stock Io’s various graphics bindings won’t build for me, & my reimplementation has a ways to go. Screenshots might be misleading, though: my goal is to have a system that’s extremely mutable in its form. Squeak’s smalltalk-based desktop is a good representation of the kind of thing I’m aiming for.
can you post some links to some examples of UIs on TV you consider good examples of what you want to do?
I’ll dig up some. Alternately, TVTropes has some lists.
Think along the lines of the way viruses are depicted in the movie Hackers – as graphical objects with apparent properties. Obviously, viruses have other reasons for not exposing their nature graphically – the whole point of them is to be hidden from & hostile to the end user – but having a graphical representation that matches the end user’s mental model of a task (as opposed to skeuomorphism, wherein it matches a programmer’s model of a device that used to accomplish a similar task, or the current norm, where the UI maps onto the structure of the programmer’s code) is desirable, even though it can’t be attained unless the end user writes it themselves. (The goal here is to minimize the artificial friction users encounter in making their computing environment a natural reflection of their mind.)
Thanks, that’s a very interesting read and I understand better now.
I have defined the ‘widget’ object as having a position, size, and bitmap.
Does this mean everything will mainly be raster (as opposed to vector). What about other visual transformations? How (un)important are they? Or maybe my question actually is whether composition will mainly be on functionality or visual appearance as well?
(I don’t plan to make non-widget objects impossible, but it’s bad form, since they’re going to be harder to find and change.)
Hmm…what about overlays for viewing and editing widgets, like corners, text cursors and bounding boxes? I guess they could all be their own separate overlay widgets.
Unfortunately, I haven’t gotten to the point of having anything render.
That might not be an issue for prototyping, except possibly for testing speed. To try it out, you might have a mock “render” loop that just prints out everything that should be drawn (and where) for that frame.
And some random questions about the implementation you linked too.
I’m a bit concerned about calculateBbox and widgetLint’s potential resource (time) consumption.
For setParent, shouldn’t the current parent, if there is one, also remove “self” as a child?
What about user input? Do they just get passed up the tree from the child? What if you want to globally change keybindings afterwards? Does the prototype-object system help with this or makes it harder?
A lot of what I’ve written here is probably too early to think about (although something like vector vs raster is pretty hard to change later on).
I definitely agree with Squeak not being inviting enough. I haven’t used Tk all that much despite having made this but did find issues with its internal model a few times.
I guess if Io is simple enough, it can even be part of the thing that’s to be rewritten/customized.
I hope you go much further with these ideas!
Does this mean everything will mainly be raster
In the particular system I’m writing, I’m only supporting raster, because I am lazy. I’m adopting the model from Menuet, because rendering becomes trivial: clear buffer, blit existing bitmaps onto buffer at given positions in Z order, flip. (I have the necessary information to later optimize out totally occuluded stuff, or keep a dirty bit in order to determine what parts of the display should be updated, if performance becomes a problem, but since unlike the Applet system in Java the user code doesn’t re-draw on visibility, it actually will be less of an issue, with the downside being the occasional half-drawn widget being rendered for one frame.)
whether composition will mainly be on functionality
Composition is performed through message-passing. My goal is to provide the GUI equivalent of unix pipes.
I guess they could all be their own separate overlay widgets.
Yeah. It cleans the system up conceptually if there are no “special” classes of widgets that don’t count as widgets.
To try it out, you might have a mock “render” loop that just prints out everything that should be drawn (and where) for that frame.
The stage I’m at in development is concerned with rewriting Io so that it can actually run my program.
I’m a bit concerned about calculateBbox and widgetLint’s potential resource (time) consumption.
This is a proof of concept system & so I’m not concerned with performance at all. If major performance problems appear, I’ll look at some of the low-hanging fruit (like the Io intepreter re-parsing and re-tokenizing the entire expression over and over) first.
What about user input? Do they just get passed up the tree from the child?
Yes, from the focused child.
What if you want to globally change keybindings afterwards?
That’s not a facility I’m supporting, though generally speaking you’d only be creating key bindings for widgets that use them, so having layers of conflicting triggers would be bad form.
Does the prototype-object system help with this or makes it harder?
It depends on how you use it. The inheritance hierarchy is distinct from the widget-packing hierarchy, and both are used for message-handling (of which input handling is a part). It’s definitely possible to make a huge mess with this.
A lot of what I’ve written here is probably too early to think about
I actually made a lot of these decisions before I started writing any code, so you’re absolutely right to ask these questions. Because I expect to have between zero and one users, performance isn’t a priority, and I’m ignoring it in favor of making everything structurally & conceptually straightforward.
if Io is simple enough, it can even be part of the thing that’s to be rewritten/customized.
Io is pretty bare-bones and I’m looking to write as much as possible in it, as opposed to Tk, where complex things like the text entry widget are basically exposed from FFI. I probably won’t expose the actual parser to be rewritten, though.
I’m curious – has there been any development on this since? Would you be interested in any volunteer work? I’ve got some time to kill, as I don’t start work for a while. PM me if you’re interested.
I haven’t done any work on this for a while, no. I’d love somebody to pick up where I left off, or work on their own projects inspired by this.
I’m likely to work on it very intermittently. I have a lot of side projects, and with the current load at work, I get a chance to commit to one maybe once every few weeks. This one is complicated, since I’m writing a whole programming language interpreter for it, so it’ll probably get less love than my simpler projects.
I’ve started poking at it in https://github.com/tekknolagi/kamui (having filtered out the subfolder from your misc repository). I’m very new to Io and this idea, so we’ll see if I get anywhere at all.
So this is a programming class aimed specifically at seniors? That sounds like a lot of fun. If it’s not an impertinent question, what sort of work/lives/hobbies did you and your classmates have before you retired / what prompted you all to get into programming?
Thanks! We had a good laugh at your comment. I don’t think the post mentions school until the very end, so it’s pretty reasonable!
Say what you will about the Ruby community, but I’ve never seen them fly into a moral panic over a tiny syntax improvement to an inelegant and semi-common construct.
The person-years and energy spent bikeshedding PEP 572 are just astoundingly silly.
Say what you will about the Ruby community, but I’ve never seen them fly into a moral panic over a tiny syntax improvement to an inelegant and semi-common construct.
Try suggesting someone use “folks” instead of “guys” sometime…
I switched to folks and do you know how satisfying of a word it is to say? “Hey folks? How’s it going folks? Listen up folks!” I love it.
On the other hand the interns weren’t too keen on “kiddos.”
A man/woman (or nerd, I guess) after my own heart! This has been my go-to for a while, until one time I walked into my wife’s work (a local CPA / tax service) and said, “What up, nerds?” It didn’t go over so well and apparently I offended some people – I guess “nerd” isn’t so endearing outside of tech?
Thankfully, I don’t think I learned anything from the encounter.
I generally only use it in a technical setting – so within my CS friend group from college, other programmers at work, etc… whenever it’s clear that yes, I am definitely not trying to insult people because I too am a nerd.
as @lmm notes above, a minimalist, consistent syntax is an important part of python’s value proposition. in ruby’s case, adding syntactic improvements is aligned with their value proposition of expressiveness and “programmer joy”, so it’s far less controversial to do something like this.
On one hand, the later implementation of the prank is somewhat clever, the pranking back part amusing. On the other hand, repeatedly annoying someone who’s in no position to figure out the prank is about as funny as locking the wheels of a wheelchair. Maybe less harm done, but still a despicable thing to do.
Once or twice, between roommates - fine. Doing so for a long period of time, and even being proud of being an ass - well, that’s not even remotely funny.
I dunno, he’s a pretty smart fellow. Almost graduated with CS+EE degrees but decided last minute to just do EE. He uses Linux as his daily driver. Your comment does not do him justice.
My dad uses Linux as his daily driver, has been for the past 10 years, he teaches CS at a respected university, and is a very smart man. Yet, when it comes to debugging his system, he has no clue. He knows all about the tools he has to teach, the programs he uses daily, but anything other than that is a black box.
Not being in a position to figure out the prank is not a derogative thing. Just because one is adept at using computers, and can compile a kernel, install drivers, doesn’t mean he’s good at looking for hacks. And there’s absolutely nothing wrong with that. It doesn’t make them less smart.
Pranking someone like that, who never suspects a hack, for a long period of time, is not funny. It is you being an ass.
I would be very interested to see how this compares with say Carp. I’m not knowledgeable in this space though so it might be universes apart.
PicoLisp has a single data type internally, and as a result doesn’t do anything fancy in terms of garbage collection (there’s no real avenue for heap fragmentation). As such it’s just a mark-sweep collector.
newlisp does do something more fancy, Automatic Memory Management in newLISP, which is similar in nature to what Interim does, and what Rust does as well, albeit in a completely different way.
newLISP follows a one reference only (ORO) rule. Every memory object not referenced by a symbol is obsolete once newLISP reaches a higher evaluation level during expression evaluation. Objects in newLISP (excluding symbols and contexts) are passed by value copy to other user-defined functions. As a result, each newLISP object only requires one reference.
newLISP memory management in practice felt like Tcl to me, and not in a good way. The details are different, but you end up doing similar kluges, where you pass a handle to data that must be manually GC’d if you need to pass large stuff around/mutate data. That’s radically different from what Rust does, both in broad strokes and in the details.
[Edit: accidentally wrote PicoLisp the first time I drafted this comment.]
Yes, Rust is undoubtedly better in practice, though far more complicated to learn, and implement (from a compiler standpoint). A couple of hacks here and there and you get “arena-like” allocation properties, and it’s easy to implement? Yeah, seems like a good trade off for small, embeddable languages, to me.
Oops! There’s some naming conflict there. I’m the author of the Carp and Rabbit you mentioned, both of which are small learning projects. https://github.com/carp-lang/Carp is probably the Lisp you are looking for.
One potential issue with your program: it pushes all input to the program before reading any of its output. In a case where the program does a significant amount of output, it may block - and in fact, deadlock, since it will stop consuming input, which may cause your driver program to block as it attempts to write to the pipe.
This might not be a real concern, though, if the amount of input/output is always limited.
Edit: a more comprehensive solution might be to loop while both pushing some input to the student program using non-blocking I/O and read some of its output (also using non-blocking I/O). Once you’ve pushed all input, you could leave the loop and assume the pipe buffer contains all significant output (as you do now), or perhaps better, flush the buffer and then sleep for a little before checking for more output (using non-blocking I/O).
Hm, interesting. The good news is there is not generally a significant amount of output – mostly user-interactive output, ~500B at a time. The bad news is you’re right. I didn’t realize non-blocking I/O in C was possible. Will investigate…
You’re absolutely right. In the cleanup for my post I accidentally removed those. I will fix that.
Interesting! Did you consider using expect to implement this? I’ve seen some pretty wild implementations using expect!
expect is a great program for driving interactive programs however you choose, check this out.
Here is test.expect:
spawn bash
set timeout 1
send "echo input1 | rev\n"
expect {
"1tupni" {
puts "Got 1tupni!"
}
timeout {
puts "didn't get 1tupni soon enough..."
exit 1
}
}
send "echo input2 | rev\n"
expect {
"2tupni" {
puts "Got 2tupni!"
}
timeout {
puts "didn't get 2tupni soon enough..."
exit 1
}
}
# Note I used `input3` here but look for `input4`
send "echo input3 | rev\n"
expect {
"4tupni" {
puts "Got 4tupni!"
}
timeout {
puts "didn't get 4tupni soon enough..."
exit 1
}
}
exit 0
And running it:
Morbo> expect ./test.expect
spawn bash
echo input1 | rev
[grahamc@Morbo:~/projects/student-programs]$ echo input1 | rev
1tupni
Got 1tupni!
echo input2 | rev
[grahamc@Morbo:~/projects/student-programs]$ echo input2 | rev
2tupni
Got 2tupni!
echo input3 | rev
[grahamc@Morbo:~/projects/student-programs]$ echo input3 | rev
3tupni
[grahamc@Morbo:~/projects/student-programs]$ didn't get 4tupni soon enough...
Morbo> echo $?
1
These are exactly the kind of articles we need more of in Haskell. Short, neither overly bogged down in theory nor afraid of talking about actual language features, and focused on helping people understand how to bridge the gap into building real Haskell applications.
As a somewhat-new-to-Haskell person, I’m of the opinion that this article could use either a bit more explanation or links to explanations for the terms it uses. For example: I understand that a monad is used to track state in a functional way and I have written a couple, but some of the language the first couple paragraphs in Layer 2 makes me feel like I am not reading English.
Well I have just finished a release of my build tool, which I’m very pleased with. I have been trying to “prove” it’s utility by builting existing software with it. It was able to make scripts with it to build jq and bash, so it’s pretty effective.
Do you have examples? I’d like to see the build script for jq.
the script is here https://gist.github.com/rain-1/f3434f4b12147d5ef62369e511a184de#file-jq-makesfile I left in the make bits as comments for comparisons sake
which generates this input for the ‘makes’ tool: https://gist.github.com/rain-1/f3434f4b12147d5ef62369e511a184de#file-jq-example
and then makes processes those build rules to execute them in parallel respecting dependency order.
the bash scripts themselves that generate files are pretty ugly, my tool so far is just the engine part. A nice declarative UI to produce the TSV files can be made separately.
So is your goal to write these makes files by hand or generate them with scripts?
they can be generated by a DSL either something similar to the make language, or embedded as a python library.
Neat, thanks!
Any reason your scripts target /bin/sh when they’re actually Bash scripts?
They won’t run, as-is on Debian, for example.
oh thats just a mistake