Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Last active September 21, 2022 04:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amcgregor/e4114c3f3f1b71e543fb to your computer and use it in GitHub Desktop.
Save amcgregor/e4114c3f3f1b71e543fb to your computer and use it in GitHub Desktop.
Additional Clueless code samples and ideas.
#!/bin/env q
# encoding: utf-8
# account.q
class Account # Account = Object.clone.with
balance = 0
method deposit(value)
self.balance += value
method withdraw(value)
self.balance -= value
method show
print("Account balance: $", self.balance)
myAccount = Account.new
myAccount.show
print("Depositing $10")
myAccount.deposit(10)
myAccount.show
variables:
this: the current context; variable lookups start here
object..parent: the class (or multiclass; i.e. object) this one inherits from
this..parent: the next variable context up, not always the next caller up
this..
macro 'integer' name
pass
macro 'integer' expr
pass
macro 'def' name . '(' . [ expr, ] . '):' ...
fn = this..child
ctx = this..parent
fn.this..parent = ctx
fn.this..update(ctx..eval(*expr))
ctx[name] = fn
# encoding: utf-8
define routine
pass
define somefunc with argument1, argument2=None, argument3=None
pass
define otherfunc with
integer argument1 = 24
string argument2 = 'hello'
float argument3 = 3.141
pass
# typecasting
xyzzy = 1 as float # (1).asFloat
yzzyx = "foo" as string # ("foo").asString -- this is double-quoted text, not a raw bytestring
built-ins
from org.q.core import __debug__
# these is a magical and built-in macros (classically 'statements')
macro # transparent function call that integrates with the parser
replace # compile-time replacements
'pass'
'return' expr
'yield' expr
'raise' expr
'continue' # stop execution of the current code block
'import' module ["as" name]
'from' module 'import' name ["as" name]
'global' name # assignments to this name within the current scope assign to the parent
'try'
'except' name [ 'as' name ]
else
replace 'except'
except Exception
replace 'return' expr
raise Success(expr)
replace 'return'
return None
replace 'yield'
yield None
replace 'raise'
raise Exception
macro name '=' expr
this..parent..set(name, this..parent..eval(expr))
replace 'forget' name
this..unset(name)
replace 'delete' name
this..parentOwning(name).unset(name)
macro 'not' expr
return this..parent..eval(expr).asBoolean.inverse
_if = macro 'if' expr ...
this.parent..result = this.parent.eval(expr).asBoolean.ifTrue(this.child)
macro [_if] 'else if' expr ...
if this.parent..result
return
this.parent..result = this.parent.eval(expr).asBoolean.ifTrue(this.parent)
macro [_if] 'else' ...
if this.parent..result
return
this.child.withContext(this.parent)()
macro 'assert' expr
if not this..parent..eval(expr)
raise AssertionError
macro 'assert' expr . ',' expr
if not this..parent..eval(expr.0)
raise AssertionError(this..parent..eval(expr.1))
replace 'break'
raise StopIteration
_while = macro 'while' expr ...
try
forever
if not this..parent..eval(expr)
raise StopIteration
this..parent..result = True
this..parent..eval(this..child)
except StopIteration
pass
macro [_while] 'else' ...
if this.parent..result
return
this..parent..eval(this..child)
_for = macro 'for' name 'in' expr ...
iterator = this..parent..eval(expr).asIterator
try
forever
this..child..this[name] = iterator.next
this..parent..result = True
this..parent..eval(this..child)
except StopIteration
iterator.close
macro [_for] 'else' ...
if this.parent..result
return
this.child
macro 'for' name 'in' expr ...
iterator = this..parent..eval(expr).asIterator
try
forever
this..child..set(name, iterator.next)
this..parent..eval(this..child)
except StopIteration
pass
for foo in 'bob'
print(foo)
define Object:.| attr
return self[attr]
define Object:..| attr
return self['_meta'][attr]
define Object:with ...
this.child.context = self
this.child()
macro 'with' expr ['as' name] ...
# First, evaluate the expression in the calling context.
obj = this.parent.eval(expr)
if obj.contains('enter')
obj.enter
exit = obj.get('exit', nil)
# If we don't want the variable to persist beyond the with block, change this to 'this.child.context'.
if this.context.contains('name')
this.parent.context[name] = obj
try
this.child
except
if exit and exit(this.exception)
raise
if exit:
exit
class Error
method init(message)
self.message = message.asText
method asString
return self..name + ': ' self.message
class NumericError: Error
method init(code, message)
self.code = code.asInteger
this.parents(message)
method asString
return self..name + ' (' + self.code + ') ' + self.message
class SliceError: Error
pass
class StopIteration: Error
pass
class Range
# Defines a for-loop style range iterator.
# You can natively loop over this object; each time it is looped over it resets its position.
method init(start=0, end=0, each=1)
self.start = start
self.end = end
self.each = each
self.i = nil
method asIterator
return self.copy
method enter
self.i = self.start
method next
value = self.i
if value > self.end
raise StopIteration
self.i += self.each
return value
List.with
method isEmpty
return self.length.asBoolean
method first
return self[0]
method last
return self[-1]
method slice(range)
if not range.implements(Range)
raise SliceError("Invalid range: " + range)
result = List.new()
for element in range
result.append(self[element])
return result
Generic Meta Attributes
parent
get(name[, default])
set(name, value)
eval(code)
Function Meta Attributes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment