To teach learners to think about Ruby in its underlying model rather than syntactic patterns they've memorized. Allow them to reason about their code in terms of how it affects the object model.
They say "The Cobbler's children have no shoes". I experienced this in my own education and continue to experience it as I continue to learn. And now, as an instructor at The Turing School of Software and Design, I see it with my students. The opacity of the tools, the cryptic or nonexistent feedback, the oversight of communicating the model or providing examples, the slow feedback loops, the systems that don't allow for feedback.
We are barefoot and our children are barefoot, and it is bullshit. This project is part of my attempt to address the issue for Ruby.
You might also be interested in Seeing Is Believing, another tool I created and use daily. It's aim wasn't quite as ambitious, but its method is similar: provide a labratory to perform experiments with a maximum of feedback and a minimum of effort.
Here is an exerpt of what it looks like when I teach the object model in class.
- A Ruby interpreter with a visual/interactive interface.
- Explore the object graph by clicking around it, following variables, and watching the algorithms execute (e.g. understand inheritance by watching it look up a method).
- Experiment by submitting your own code, seeing how it is interpreted, tweaking it and observing the difference.
- This is not intended to run production code, it will always choose transparency over optimization.
- This will eventually be a Ruby Interpreter that attempts to expose all of its state and algorithms as data structures that can be reflected on. Once this is accomplished, it becomes a matter of providing a user-interface to draw the visualization and allow interactive exploration.
- It will run in the browser to reduce the setup and know-how required to try it. This is important because I think it's significantly impacted adoption of SeeingIsBelieving, even though it's one of the most effective tools a learner could use (to be fair, that depends on whether the learner learns via hypothesizing and experimenting).
- I might also try turning it into a command-line tool with Atom Shell. This has value because once a learner sees it as a viable tool, they can run it locally, without leaving their development environment. Which in turn allows them to run it against code that has more than one file (the web interface will likely be a single Ace editor, thus it can handle only one file). Of course, that's exponentially more ambitious than this project is at present.
- Install parser dependencies
- You will need Ruby. I'll leave that to you O.o
cd parser
bundle
if this fails, you may need to firstgem install bundler
if this fails, probably your Ruby is installed at a global level or something.cd ..
rake parser:test
- Start the parser server
$ rake parser:server:start
- Hit it with curl
curl --silent localhost:3003 -d 'puts "hello, world"'
- I like to pile the output of that through jq for readability
$ curl --silent localhost:3003 -d 'puts "hello, world"' | jq . { "type": "send", "target": null, "message": "puts", "args": [ { "type": "string", "value": "hello, world", "location": { "filename": "(eval)", "begin": 5, "end": 19 } } ], "location": { "filename": "(eval)", "begin": 0, "end": 19 } }
- Here is a list of all AST nodes, We need to make sure we can handle all of them.
- Video about parsing expressions in Ruby Recommended by Ryan Davis
- Bootstraping
-
If we could do this, then we wouldn't need the server
-
Would need to implement the C-level Rack lib, which looks to be about 800 LOC, and then just parse the runtime
-
Would need some way to represent the file system.
-
Deps for Parser: (parser, racc, ast)
-
Deps for RubyParser: (ruby_parser, racc, sexp_processor), these look much smaller
-
Might be worth including the original Ruby source code with the JSON ast. e.g.
{"files": [{"name": "gems/some_gem/lib/some_gem.rb", "body": "class SomeGem\n def some_method\n end\nend"} ], "ast": "what we're currently serving for ast, but with file info that references the provided files" }
-
Alternatively, if we could fake out the file system, like FakeFS, we could straight ship the file system with it.
-
Can they host it locally? Would get around the need to mock the file system
-
- Choose more minified keys since certain tasks could lead to massive ASTs (e.g. parsing the parser)
- We could restrict syntax at the parser level (e.g. add a challenge where you are only allowed to use a subset of features so that student has to learn alternate ways to handle a situation, and syntactically enforce the constraint.)
- Could apply interesting constraints at the ast level (e.g. "no classes", "only loca vars", etc), which would require them to explore other ways of doing things that they normally wouldn't be exposed to.
- Potentially relevant
- List of Rubinius bytecodes
- RubySpec, Brian's work to formally define Ruby's behaviour. Looks like this is integration for MRI.
- RubySpec is reborn mixed feelings here, I'm really glad it's still being maintained, but seems like an FU to Brian.
- I think this is where Ruby's specification starts
as in you can presumably do something like
ruby test/runner.rb
decided to go look at it to see if it seemed viable as a test suite (as in "doesn't depend on a C implementation"), and it looks like it should be runnable. Depending on how serious I get, probably worth hitting that one and RubySpec simultaneously for a bit. - Official Ruby Spec I haven't looked into it yet. Got the link from the rebuttal of Brian's post. UPDATE: it costs $200 and is for Ruby 1.8 YorickPeterse has an excellent rebuttal of why it's bad for RubySpec to die. It's really annoying that MRI sees itself as "whatever the fuck we happened to do is what Ruby is".
- Inspiration
- Omniscient Debugger Holy shit, this doesn't even sound all that hard!
- Not sure, but looks like it has some interesting philisophical implications regarding how we think about software (ie thinking of it not as an app or machine)
- Debug mode is the only mode discusses Bret Victor, some good looking links
- Video Building an interpreter (30 min) Great talk by Ryan Davis about buliding an interpreter
- Video about type inferrence (possibly dealing with Soft Typing) by Loren Segal, he recommended it at RubyConf 2014
- Time Travel For Debugging at Rubyconf "With only a few restrictions and side-effects we will learn how to construct and use a time machine."
- Potential drawing libraries / platforms
- Drawing on the canvas directly
- WebGL
- Elm
- paper.js
- /Users/josh/deleteme/paperjs_workshop (Joanne's workshop)
- three.js
- mathbox2 - http://acko.net/files/pres/siggraph-2014-bof/online.html
- JS Game Engines
- Working with js
- https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial // Canvas tutorial
- https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_usage // Canvas basic usage
- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent // keyboard events
- https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener // binding callback to event
- Embedding into Miniature Octo Ironman
- Ability to display in the code editor what the browser is currently interpreting (e.g. highlighting current expression)
- Either highlight in editor or draw independently
// Highlighting. note that it's placing the range in the wrong place. Not sure why // might get them to the right place: https://github.com/ajaxorg/ace/issues/2130#issuecomment-54609425 // might be necessary to keep them in right place if user edits/scrolls (probably turn this off during its execution, though) editor.getValue(); // returns textual code to be sent to interpreter ace.Range = ace.require('ace/range'); // makes the range code available r = new ace.Range(4, 2, 4, 6); // creates a Range object on line 4, cols 2-6 s = editor.getSession(); // returns an EditSession sr = r.toScreenRange(s); // maps the underlying range to a range on the screen n = s.addMarker(sr, 'test-marker', 'MYMARKERTYPE', false) // adds the screen range to the editing session $('.test-marker').css({background: 'green'}); // shitty way to add a background (gets overwritten when redrawn, I think s.removeMarker(n); // remove the marker
- Human explanation of what it's doing and why. e.g. "in order to define a class, we need to create a constant, create this instance, etc..."
- Binary with Atom Shell
- For making native GUI apps by treating them like the browser (builds on Chromium)
- forum
- repo
- example app (mine's in deleteme folder, I think)
- Getting better at the domain
- Ability to see what they're interested in without getting spammed (e.g. "show me only code executing in my file")
- codeschool.org course on game programming includes info like how to work with 2D and 3D structures, and example game codebases.
- Short summary of best points in the Design of Every Day Things
- The 7 stages of action
- Thoughts and links about tools like these, from authors of Light Table.
- Example Centric programming
- Local state is harmful haven't figured out its point, but I imagine this conclusion is drawn from a deeper principle
- Other cool tools that could serve as inspiration
- UX for Bing search
- Wolfram Deployment API apparently they are doing crazy cool shit, worth checking out to get ideas... and possibly use, if it's as awesome as people imply with their hype
- Javascript programming game A take on what it might be like to use games to teach programming
- Codingame Michael sent me
- Game dev reading group for Challenges for Game Designers led by JEG2. Hoping to use some of these ideas to make this fun for students to work in.
- Challenges
- Constraints
- Not able to use the mouse (just have to figure out how to disable the mouse in the Ace editor)
- Constraints
- Trace This Variable
- ie "@a was set in #initialize, from local var "a", that came from param the param that came from X.new(1)"
- "bridge the gap" show an object model, user writes code to get to it
- Simon
- watch interpreter trace the path of execution
- you reproduce it
- Be the ruby interpreter
- you are given some code,
- some controls, then you use the controls to specify what the interpreter would do
- (remove the keyboard syntax as a barrier to the object model)