Difference between revision 18 and current revision
No diff available.Table of Contents for Programming Languages: a survey
what can be a key? can you add hash fns to custom data?
http://docs.python.org/dev/library/enum.html
note: this link describes the benefits of enums over just using preprocessor macros, e.g. C #defines: http://codingrelic.geekhold.com/2008/10/ode-to-enum.html
unicode? bytestring?
some syntaxes:
"$x" e.g Perl
"{x}" e.g. Hoon
"%d" % (x) e.g. Python
"\(x)" e.g. Yeti, Apple Swift
`${x + 1}` in Javascript ES6
ML, Haskell
OMeta: parsing on data http://www.vpri.org/pdf/tr2008003_experimenting.pdf
in an object-oriented language without reflection or pattern-matching, the only way to make behavior conditional upon object class is through methods (which are polymorphic on the type of the object they are a part of). In such a case, if it is desired for the behavior of a method depend on its arguments, the Visitor pattern can be used (e.g.
" package syntax;
abstract class ExpressionVisitor? { abstract void visitIntExp(IntExp? e); abstract void visitAddExp(AddExp? e); }
abstract class Expression { abstract void accept(ExpressionVisitor? v); }
class IntExp? extends Expression { int value;
void accept(ExpressionVisitor v) { v.visitIntExp(this); }}
class AddExp? extends Expression { Expression e1, e2;
void accept(ExpressionVisitor v) { v.visitAddExp(this); }}
The interest of this construction is that it is now possible to define operations on expressions by subclassing ExpressionVisitor?. This can even be done in a different package, without modifying the expression hierarchy classes.
Behaviour can now be defined on Expressions
package tools;
class PrettyPrint? extends ExpressionVisitor? { void visitIntExp(IntExp? e) { System.out.print(e.value); }
void visitAddExp(AddExp e) { e.e1.accept(this); System.out.print(" + "); e.e2.accept(this); } } " -- example from nice.sourceforge.net/visitor.html
todo: haskell example
e.g. Apple Swift (note this Apple Swift example and some others are from https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/LandingPage/index.html ):
" let size = (20, 40)
switch size { case let (width, height) where width == height: println("square with sides \(width)") case (1..10, 1..10): println("small rectangle") case let (width, height): println("rectangle with width \(width) and height \(height)") }"
https://www.python.org/dev/peps/pep-0636/
Specification https://www.python.org/dev/peps/pep-0634/
Motivation and Rationale https://www.python.org/dev/peps/pep-0635/
Tutorial https://www.python.org/dev/peps/pep-0636/
GADTs
'pattern matching' is a key operation on these; this is a SWITCH statement on the form of the data ('form' meaning which is the outermost constructor; this is then extended to be a nested top-down pattern from the outermost constructor to some ways in), combined with a destructuring bind in each case.
As a control primitive, pattern matching on ADTs can be thought of as if the nested query on the form of the constructor is a shortcut for a bunch of nested if-thens. Since ADTs and pattern matching are generally seen together in languages, ADTs are closely related to a control structure, too.
ADTs for OOP
e.g. scala http://docs.scala-lang.org/tutorials/tour/case-classes.html
the point is to be able to perform pattern matching, possibly with guards
possible features:
Common examples:
LINQ
macros, calls continuations, call stacks, ASTs/expressions
Wadler http://homepages.inf.ed.ac.uk/wadler/papers/view/view.ps 1987
In some languages, a..b means "the list with every value x such that a <= x <= b, in order". Eg 0..5, eg 'a'..'z', eg 'A'..'Z'
In Perl6, a..b are expanded in place when concatenated with ',', for example a list of the alphanumeric characters may be written ('a'..'z','A'..'Z',0..9) (todo: am i understanding that correctly?)
In Perl6, a..^b is like a..b but with b excluded, ie a <= x < b.
In Perl6, ^x is shorthand for 0..x
In Perl6, lazy list literals can be constructed by putting "... *" at the end. Eg:
constant fibonacci-list = 0, 1, 1, &[+] ... *;
or, rephrasing &[+]:
constant fibonacci-list = 0, 1, 1, * + * ... *;
Perl6 has 'deductive lists':
constant powers-of-two = 2, 4, 8, 16, 32, 64 ... *;
In Perl6, lists can be made 'auto-threading' via the '>>' postfix operator.
(thanks [1])
In Perl6, lists can be made 'auto-threading' via the '>>' postfix operator. Eg:
(0..5)>>.say;
(thanks [2])
"Lazy sequences are the sort of thing that you don't care about until you need to process a ten-million-line file (or whatever) and suddenly find that your program is slowing down for pointless memory allocations up-front -- then they become unbelievably important. " -- drostie
labeled, hyper, etc
..and graph dbs
http://www.hypergraphdb.org/docs/hypergraphdb.pdf
transactions
and 'cd' and 'pwd' in filesystems
headers
seek
also, Multiversion concurrency control (MVCC) as a database implementation technique (vs locking)
versioned dbs that can reconsutruct state as of some point in the past?
flat plaintext files that can be version controlled, vs databases
plaintext works esp well for idempotent, journaled, or slowly/rarely concurrently 'mutating' stuff eg accounting, source code
ACID dbs work esp. well for multiuser ACID usage with changes of small granularity
object/relational divide
access (sub)field
.next()
in the absence of language-supported iterators, some ways to implement equivalent functionality (quoted and paraphrased from [3]):
cons, head, tail
S-exprs
datomic?
"a new form of pattern, ... that means apply an "expression to whatever we're trying to match against, and then match the result of that application against the pattern" -- [4]
Haskell has them.
eg http://stackoverflow.com/questions/24700762/or-patterns-in-haskell
Ocaml has them.
https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/syntax-extns.html#pattern-synonyms
Haskell has them.
example in C# (adapted from [5]):
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
// numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num;
foreach (int num in numQuery) { Console.Write("{0,1} ", num); }
data sources:
filtering:
ordering and grouping and partitioning and element operations:
descending): sort the results |
joining:
quantifier operations (note: no C# query expression syntax):
aggregations (note: no C# query expression syntax):
set and other whole-sequence operations (note: no C# query expression syntax):
transforming/mapping and projection:
generation (note: no C# query expression syntax):
comparison (note: no C# query expression syntax):
See [6].
from cust in customers where cust.City == "London" orderby cust.Name ascending select cust;
queryCustomersByCity is an IEnumerable<IGrouping<string, Customer>> var queryCustomersByCity = from cust in customers group cust by cust.City;
// customerGroup is an IGrouping<string, Customer> foreach (var customerGroup in queryCustomersByCity) { Console.WriteLine(customerGroup.Key); foreach (Customer customer in customerGroup) { Console.WriteLine(" {0}", customer.Name); } }
custQuery is an IEnumerable<IGrouping<string, Customer>> var custQuery = from cust in customers group cust by cust.City into custGroup where custGroup.Count() > 2 orderby custGroup.Key select custGroup;
var innerJoinQuery = from cust in customers join dist in distributors on cust.City equals dist.City select new { CustomerName? = cust.Name, DistributorName? = dist.Name };
" In LINQ you do not have to use join as often as you do in SQL because foreign keys in LINQ are represented in the object model as properties that hold a collection of items. For example, a Customer object contains a collection of Order objects. Rather than performing a join, you access the orders by using dot notation:
from order in Customer.Orders...
"
Links:
, &, ~, % |
https://harelang.org/tutorials/introduction/#tagged-unions-in-depth
---
todo: 'fluids' eg https://www.gnu.org/software/guile/docs/master/guile.html/Fluids-and-Dynamic-States.html#Fluids-and-Dynamic-States
---
Often in low-level or minimalist languages, one sees constraints on fundamental composite data structures.
the common ones:
---
When specifying a way to create a sequence of consecutive integers (a range), two common choices are right-exclusive ranges (e.g. 1..3 means 1,2) and inclusive ranges (e.g. 1..3 means 1,2,3).
Inclusive ranges are more intuitive.
Right-exclusive ranges have some advantages:
---
https://odin-lang.org/docs/overview/#using-statement
---
---
great explanation of ADTs and their use for "Encoding and Enforcing Invariants in the Type System", with an example, in https://gregoryszorc.com/blog/2021/04/13/rust-is-for-professionals/ section "Encoding and Enforcing Invariants in the Type System".
---
eg Python's @dataclass
eg Ruby's https://blog.saeloun.com/2022/11/22/data-immutable-object.html
---