Fragments: October 21
-
Gergely Orosz is frustrated at those that entered his explicitly “No AI”
essay competition and used AI. He goes on to say:
When I start to suspect some p...
13 hours ago
@ARTICLE{2015arXiv150500149C,
author = {{Clark}, T. and {Sammut}, P. and {Willans}, J.},
title = "{Applied Metamodelling: A Foundation for Language Driven Development (Third Edition)}",
journal = {ArXiv e-prints},
archivePrefix = "arXiv",
eprint = {1505.00149},
primaryClass = "cs.SE",
keywords = {Computer Science - Software Engineering},
year = 2015,
month = may,
adsurl = {http://adsabs.harvard.edu/abs/2015arXiv150500149C},
adsnote = {Provided by the SAO/NASA Astrophysics Data System}
}
Historically a high proportion (round 30%, sometimes up to 50%) of novice programmers fails to learn to program, and the level of achievement amongst the successful is often disappointing. Until recently the reasons for this miserable state of affairs were mysterious. Now we have some insight, we have a test which reveals important differences between novices, and two potential explanations. The gloomy explanation is that there is a 'geek gene'; even if that is true, we may be able to identify the geeks. The hopeful explanation is that there is something peculiar about programming courses, which elevates difficulties into show-stopping obstacles; if true, we have at last identified one such obstacle, we can hope to identify others, we can diagnose those who are stuck and we may at last be able to do something about it.They have devised some tests to be given to first year students before and during a programming course. The tests are based on asking students to interpret programs and visual representations of system states in a way that identifies students that can induce the rules of a machine. The test identifies those that cannot work out the rules, those that can work out a consistent set of rules that happen to be wrong, and those that get the correct set of rules.
Clicking on 'add' allows the current address book to be viewed and edited as shown on the rightcontext Root @Operation list(out,root,prefix,indent) let path = root + "/" + prefix then dir = Directory(path,Seq{".*xmf",".*java",".*txt"}) in dir.build(1); format(out,"~V<li><a href='#'>~S</a>~%",Seq{indent,dir.name.splitBy("/",0,0)->last}); format(out,"~V<ul>~%",Seq{indent+2}); @For x in dir.contents() do let name = x.name.splitBy("/",0,0)->last in if not Set{".svn","META-INF"}->includes(name) then if x.isKindOf(Directory) then list(out,root,prefix + "/" + name ,indent+2) else if name.hasSuffix("java") then format(out,"~V<li class='item'><a onclick='display_java('~S');'>~S</a></li>~%",Seq{indent+2,prefix+"/"+name,name}) else format(out,"~V<li class='item'><a href='~S' target='FILES'>~S</a></li>~%",Seq{indent+2,prefix+"/"+name,name}) end end end end end; format(out,"~V</ul>~%~V</li>~%",Seq{indent+2,indent}) end end
export test1,test2
// We need syntax constructors for Record and Field:
import 'src/xpl/exp.xpl'
// We need list operations:
// take([1,2,3],2) = [1,2]
// drop([1,2,3],2) = [3]
// foldr(f,g,b,[1,2,3]) = g(f(1),g(f(2),g(f(3),b)))
import 'src/xpl/lists.xpl'
// Define some functions to be used as args to foldr:
combine(left,right) = [| fun(l) ${left}(l,fun(r,l) r + ${right}(l)) |]
id(x) = x
empty = [| fun(l) {} |]
// Define a function that constructs *the syntax* of a field extractor:
// extractor('name',5) = [| fun(l,k) k({name=asString(take(l,5))},drop(l,5)) |]
extractor(n,i) =
let record = Record([Field(n,[| asString(take(l,${i})) |])])
in [| fun(l,k) k(${record},drop(l,${i})) |]
// Define the grammar to consists of a sequence of fields.
// Each field builds an extractor. All extractors are combined
// into a mapping from a sequence of character codes to a record:
grammar = {
fields -> fs=field* { foldr(id,combine,empty,fs) };
field -> n=name whitespace ':' i=int { extractor(n,i) };
int -> whitespace n=numeric+ { Int(asInt(n)) };
whitespace -> (32 | 10 | 9 | 13)*;
name -> whitespace l=alpha ls=alpha* { asString(l:ls) };
alpha -> ['a','z'];
numeric -> ['0','9']
}
// Here is a use of the language: a customer is a name (5 chars) followed
// by an address (15 chars), followed by an account number (3 chars):
customer =
intern grammar {
customer:5
address:15
account:3
}
// The customer map is used by applying it to a stream of char codes:
input = [102,114,101,100,32,49,48,32,77,97,105,110,32,82,111,97,100,32,32,32,53,48,49]
test1() = customer(input)
// Just to show everything is first-class:
test2() = map(customer,repeat(input,10))
To use XPL you download the ZIP file (link above). It is developed as an Eclipse project, but can also be run stand-alone. The interpreter is in the xpl package in the source folder. If you run the Interpreter as a Java application in Eclipse then the console becomes an XPL top-level loop that you can type XPL commands to. Here is a transcript of the example given above (user input after a '>' followed by XPL output):[src/xpl/xpl.xpl 2353 ms,136]
> import 'src/xpl/split.xpl';
[src/xpl/split.xpl 179 ms,262]
[src/xpl/exp.xpl 26 ms,404]
[src/xpl/lists.xpl 108 ms,164]
> test1();
{customer=fred ;address=10 Main Road ;account=501}
> test2();
[{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501},
{customer=fred ;address=10 Main Road ;account=501}]
> There is currently no user documentation (contact me if you are interested in this). But there are some technical articles: language modules in XPL, modular interpreters in XPL, and parsing infix operators using XPL. In addition the source code contains a number of examples in the xpl folder.