-
Notifications
You must be signed in to change notification settings - Fork 10
Language Features
Internally, all user code is run through the Ruby VM, making it difficult to label Zajal as a completely new language on its own. Instead, like Processing is to Java, Zajal is based on Ruby and largely compatible with it, but deviates in a few important areas.
The interpreter is written as an openFrameworks application in C++ to benefit from OF's event loop. The API is written mostly in C to interface with the Ruby VM and wrap OF's objects and functions. Experimental and complex parts of the API are implemented in Ruby with plans to re-implement them in C if performance becomes an issue.
Note: This page only describes features that are particular to Zajal and assumes a knowledge of Ruby. For a more complete overview without such assumptions, see Syntax.
Zajal programs are not runnable as Ruby code. Feeding a Zajal program to a stock Ruby interpreter will cause it to complain that setup
and update
are not defined. This is because, in an effort to keep user code as focused and streamlined as possible, calls like require "zajal"
that you may expect are not needed. Details like that are taken care of by the Zajal interpreter.
Programs are structured much as they are Processing, albeit without the Java cruft.
t = 0
setup do
size 200, 200
smoothing true
end
update do
t += 0.1
end
draw do
circle width/2 + cos(t) * 10, height/2 + sin(t) * 10, 5
end
# this is a local variable with top level scope
k = 0
# top level local in event block:
# always works, because this is a closure
update do
k += 1
end
# top level local in method:
# does not work in ruby, because method calls change scope
# made to work in zajal
def somefunction n
return n / k
end
# top level local with same name as method parameter:
# currently errors out.
# not sure if this should be disallowed, or if k should be shadowed here
def otherfunction k
k += 10
return k ** 2
end
# normal class definition, but attr_accessor and
# friends can be left out
class Car
def initialize
@speed = 10
@weight = 52.75
@name = "VW Polo"
end
end
polo = nil
setup do
polo = Car.new
end
# instance variables can be set
update do
polo.speed -= 0.1
end
# instance variables can read
draw do
text polo.name
text polo.speed
end
# to restore default Ruby behavior
# attr_* methods set class to default Ruby behavior
class Magazine
attr_accessor :current_page
def initialize
@current_page = 0
@name = "The New Yorker"
end
end
m = Magazine.new
# works
m.current_page += 1
# doesn't work, name= method not defined
m.name = "Wired"
# explicitly set class to default Ruby behavior
class Lamp
attr_private
def initialize
@wattage = 60
end
end
# will result in error, no wattage= method defined
l = Lamp.new
l.wattage += 10
# after pressing the 'a' key, all of the following evaluate to true
key_pressed do |key|
key == "a"
key == :a
key =~ /a/
key == 97 # this might be removed
end
# after pressing the left arrow key, all of the following evaluate to true
key_pressed do |key|
key == :left
key == 357
end
# after pressing the '4' key, all of the following evaluate to true
key_pressed do |key|
key == "4"
key == :'4'
key == 52 # this might be removed in favor of key == 4
end
# case-when constructs work as expected
key_pressed do |key|
case key
when "a" then # ...
when :left, :right then # ...
when /[A-Z]/ then # ...
end