proj-oot-ootNotes15


" things rust shipped without Jul. 3rd, 2015 08:26 am graydon2: (Default) [personal profile] graydon2 Well-known things I'm very proud that rust shipped 1.0 without:

    null pointers
    array overruns
    data races
    wild pointers
    uninitialized, yet addressable memory
    unions that allow access to the wrong field

Less-well-known things I'm very proud that rust shipped 1.0 without:

    a shared root namespace
    variables with runtime "before main" static initialization (the .ctors section)
    a compilation model that relies on textual inclusion (#include) or textual elision (#ifdef)
    a compilation model that relies on the order of declarations (possible caveat: macros)
    accidental identifier capture in macros
    random-access strings
    UTF-16 or UCS-2 support anywhere outside windows API compatibility routines
    signed character types
    (hah! vertical tab escapes (as recently discussed) along with the escapes for bell and form-feed)
    "accidental octal" from leading zeroes
    goto (not even as a reserved word)
    dangling else (or misgrouped control structure bodies of any sort)
    case fallthrough
    a == operator you can easily typo as = and still compile
    a === operator, or any set of easily-confused equality operators
    silent coercions between boolean and anything else
    silent coercions between enums and integers
    silent arithmetic coercions, promotions
    implementation-dependent sign for the result of % with negative dividend
    bitwise operators with lower precedence than comparison operators
    auto-increment operators
    a poor-quality default hash function
    pointer-heavy default containers

Next time you're in a conversation about language design and someone sighs, shakes their head and tells you that sad legacy design choices are just the burden of the past and we're helpless to avoid repeating them, try to remember that this is not so. " -- http://graydon2.dreamwidth.org/218040.html

discussion: https://news.ycombinator.com/item?id=9827051


" Packages are Ciao files that contain syntax and compilation rules and that are loaded by the compiler as plugins and unloaded when compilation finishes. Packages only modify the syntax and semantics of the module from where they are loaded, and therefore, other modules can use packages introducing incompatible syntax/semantics without clashing. " -- http://clip.dia.fi.upm.es/papers/hermenegildo11:ciao-design-tplp.pdf


what does this mean?:

" Semantically, the extension is related to logic-functional languages like Curry (Hanus et al. ) but relies on flattening and resolution, using freeze/2 for lazy evaluation, instead of narrowing. " -- http://clip.dia.fi.upm.es/papers/hermenegildo11:ciao-design-tplp.pdf

---

---

andrewchambers 17 hours ago

The thing I like about clojurescript is the fact that it has a linker and library system which makes sense.

reply


fact(N) := N=0 ? 1 10

N>0 ? N * fact(--N).

fact is written using a disjunction (marked by “

”) of guards (delimited by “ ? ”), which together commit the system to the first matching choice.

?- use_package(functional). ?- X = ~nrev([1,2,3]). X = [3,2,1] ?- [3,2,1] = ~nrev(X). X = [1,2,3]

Since, in general, functional notation is just syntax, and thus, no directionality is implied, the second query to nrev/2 just instantiates its argument.

---

:- module(someprops, _, [functional, hiord]). color := red

list := []list_of(T) := []sorted := []sorted([X,Y:- module(someprops, _, []). color(red). color(blue). color(green). list([]). list([_:- use_module(engine(hiord_rt)). list_of(_, []). list_of(T, [Xsorted([]). sorted([_]). sorted([X,Y
blue green.
[_list].
[~T list_of(T)].
[_].
Z]) :- X @< Y, sorted([YZ]).
T]) :- list(T).
Xs]) :- call(T, X), list_of(T, Xs).
Z]) :- X @< Y, sorted([YZ]).

Fig. 3. Examples in Ciao functional notation and state of translation after applying the functional and hiord packages.

-- http://clip.dia.fi.upm.es/papers/hermenegildo11:ciao-design-tplp.pdf

todo: i dont understand:

list_of(T) := []

[~T list_of(T)].

:- use_module(engine(hiord_rt)). list_of(_, []). list_of(T, [X

Xs]) :- call(T, X), list_of(T, Xs).

---

" Other logic programming flavors: alternatively to the above, by not loading the classic Prolog package(s) the user can restrict a given module to use only pure logic 226 M. V. Hermenegildo et al. programming, without any of Prolog’s impure features. 2 " -- http://clip.dia.fi.upm.es/papers/hermenegildo11:ciao-design-tplp.pdf

---

Additional computation rules: in addition to the usual depth-first, left-to-right exe- cution of Prolog, other computation rules such as breadth-first, iterative deepening, tabling (see later), and the Andorra model are available, again by loading suitable packages. This has proved particularly useful when teaching, since it allows post- poning the introduction of the (often useful in practice) quirks of Prolog (see the slides of a course starting with pure logic programming and breadth-first search in http://www.cliplab.org/logalg ).

---

" I lovingly reused features from many languages. (I suppose a Modernist would say I stole the features, since Modernists are hung up about originality.) Whatever the verb you choose, I've done it over the course of the years from C, sh, csh, grep, sed, awk, Fortran, COBOL, PL/I, BASIC-PLUS, SNOBOL, Lisp, Ada, C++, and Python. To name a few. To the extent that Perl rules rather than sucks, it's because the various features of these languages ruled rather than sucked.

But note something important here. I left behind more than I took. A lot more. In modern terms, there was a lot of stuff that sucked. Now, on the feature set issue, Perl is always getting a lot of bad press.

I think people who give bad press to Perl's feature set should have more angst about their reporting.

I picked the feature set of Perl because I thought they were cool features. I left the other ones behind because I thought they sucked.

More than that, I combined these cool features in a way that makes sense to me as a postmodern linguist, not in a way that makes sense to the typical Modernistic computer scientist. Recall that the essence of Modernism is to take one cool idea and drive it into the ground. It's not difficult to look at computer languages and see which ones are trying to be modern by driving something into the ground. Think about Lisp, and parentheses. Think about Forth, and stack code. Think about Prolog, and backtracking. Think about Smalltalk, and objects. (Or if you don't want to think about Smalltalk, think about Java, and objects.)

Think about Python, and whitespace. Hi, Guido.

Or think about shell programming, and reductionism. How many times have we heard the mantra that a program should do one thing and do it well? " -- http://www.wall.org/~larry/pm.html

---

---

" MMIX versus reality. A person who understands the rudiments of MMIX programming has a pretty good idea of what today's general-purpose computers can do easily; MMIX is very much like all of them. But MMIX has been idealized in several ways, partly because the author has tried to design a machine that is somewhat "ahead of its time" so that it won't become obsolete too quickly. Therefore a brief comparison between MMIX and the computers actually being built at the turn of the millennium is appropriate. The main differences between MMIX and those machines are:

ffl Commercial machines do not ignore the low-order bits of memory addresses,

as MMIX does when accessing M8[A]; they usually insist that A be a multiple of 8. (We will find many uses for those precious low-order bits.)

ffl Commercial machines are usually deficient in their support of integer arithmetic. For example, they almost never produce the true quotient bx=yc and true remainder x mod y when x is negative or y is negative; they often throw away the upper half of a product. They don't treat left and right shifts as strict equivalents of multiplication and division by powers of 2. Sometimes they do not implement division in hardware at all; and when they do handle division, they usually assume that the upper half of the 128-bit dividend is zero. Such restrictions make high-precision calculations more difficult.

ffl Commercial machines do not perform FINT and FREM efficiently. ffl Commercial machines do not (yet?) have the powerful MOR and MXOR operations. They usually have a half dozen or so ad hoc instructions that handle only the most common special cases of MOR.

ffl Commercial machines rarely have more than 64 general-purpose registers. The

256 registers of MMIX significantly decrease program length, because many variables and constants of a program can live entirely in those registers instead of in memory. Furthermore, MMIX's register stack is more flexible than the comparable mechanisms in existing computers.

All of these pluses for MMIX have associated minuses, because computer design always involves tradeoffs. The primary design goal for MMIX was to keep the machine as simple and clean and consistent and forward-looking as possible, without sacrificing speed and realism too greatly.

"

what MOR is (this is much easier to read at http://www-cs-faculty.stanford.edu/~uno/fasc1.ps.gz page 11 (PDF page 16)):

"

We can also regard an octabyte as an 8 \Theta 8 Boolean matrix, that is, as an 8 \Theta 8 array of 0s and 1s. Let m(x) be the matrix whose rows from top to bottom are the bytes of x from left to right; and let m

T

(x) be the transposed matrix,

whose columns are the bytes of x. For example, if x =

9e 37 79 b9 7f 4a 7c 16 is

the octabyte (2), we have

m(x) =

0 B B B B B B B B B @

1 0 0 1 1 1 1 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 1 1 0 1 0 0 1 0 1 0 0 1 1 1 1 1 0 0 0 0 0 1 0 1 1 0

1 C C C C C C C C C A

; m

T

(x) =

0 B B B B B B B B B @

1 0 0 1 0 0 0 0 0 0 1 0 1 1 1 0 0 1 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 0 0 1 0 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 0 0 0

1 C C C C C C C C C A

(10)

This interpretation of octabytes suggests two operations that are quite familiar to mathematicians, but we will pause a moment to define them from scratch.

If A is an m \Theta n matrix and B is an n \Theta s matrix, and if ffi and ffl are binary operations, the generalized matrix product A

ffi

ffl B is the m \Theta s matrix C defined

by

Cij = (Ai1 ffl B1j) ffi (Ai2 ffl B2j) ffi \Delta \Delta \Delta ffi (Ain ffl Bnj) (11)

for 1 ^ i ^ m and 1 ^ j ^ s. [See K. E. Iverson, A Programming Language (Wiley, 1962), 23-24; we assume that ffi is associative.] An ordinary matrix product is obtained when ffi is + and ffl is \Theta , but we obtain important operations

11

12 BASIC CONCEPTS 1.3.1' on Boolean matrices if we let ffi be . or \Phi :

(A

.

\Theta

B)ij = Ai1B1j . Ai2B2j . \Delta \Delta \Delta . AinBnj?; (12)

(A

\Phi

\Theta

B)ij = Ai1B1j \Phi Ai2B2j \Phi \Delta \Delta \Delta \Phi AinBnj?: (13)

Notice that if the rows of A each contain at most one 1, at most one term in (12) or (13) is nonzero. The same is true if the columns of B each contain at most one 1. Therefore A

.

\Theta

B and A

\Phi

\Theta

B both turn out to be the same as the ordinary

matrix product A

+

\Theta

B = AB in such cases.

ffl MOR $X,$Y,$Z (multiple or): m

T

($X) m

T

($Y)

.

\Theta

m

T

($Z);

equivalently, m($X) m($Z)

.

\Theta

m($Y). (See exercise 32.)

ffl MXOR $X,$Y,$Z (multiple exclusive-or): m

T

($X) m

T

($Y)

\Phi

\Theta

m

T

($Z);

equivalently, m($X) m($Z)

\Phi

\Theta

m($Y).

These operations essentially set each byte of $X by looking at the corresponding byte of $Z and using its bits to select bytes of $Y; the selected bytes are then ored or xored together. If, for example, we have

$Z =

01 02 04 08 10 20 40 80; (14)

then both MOR and MXOR will set register $X to the byte reversal of register $Y: The kth byte from the left of $X will be set to the kth byte from the right of $Y, for 1 ^ k ^ 8. On the other hand if $Z =

00000000000000ff, MOR and MXOR

will set all bytes of $X to zero except for the rightmost byte, which will become either the OR or the XOR of all eight bytes of $Y. Exercises 33-37 illustrate some of the many practical applications of these versatile commands. "


m_mueller 1 day ago

One thing that almost always gets overlooked when critizing / trying to innovate on Xerox Parc-like interfaces, is discoverability. Look at departures from this interface (or predecessors of it) and you'll almost always find a system where it's hard for users to discover what they can do and how their actions will affect the state. Most prominently:

The only interface that has improved on discoverability so far, is OSX, especially with its integrated spotlight search in each application's help menu.

What I'd like to see is a CLI that (a) understands objects by default (i.e. PowerShell?) and (b) is discoverable, for example by using mouse interactions when you're trying to learn.

(a) would mean that the command line applications become much easier to compose. Imagine something like list / dict comprehensions in the command line:

ls

[entry.created for entry in $@ if entry.filename[0] == 'a']sort

(b) would mean that you could hover each of the commands above, inspect the possible parameters, default values, examples without having to execute anything. The whole interface could get much richer as well, for example if the output of your commands is a list of objects that have the same attributes (e.g. `ls`), it would display it in a table where each column is sortable using gasp the mouse.


" Out of the frustration with AMQP I've started my own ZeroMQ? project. No committee this time! Surely, I was able to make it functionally complete? Well, no. I've tried to make it do too much. It is a compatibility library, a async I/O framework, a message delimitation protocol and a library of messaging patterns. Today, almost eight years after its inception, the project is still under active development and heading towards the point where it will be able to send email.

Next one: nanomsg. An alternative to ZeroMQ?. I've tried to limit the scope of project by splitting the transport functionality as well as messaging patterns into separate plug-ins. I was partially successful, but it is still too big a chunk to swallow in a single piece. "

-- http://250bpm.com/blog:50


python 3.5:

zipapp¶

The new zipapp module (specified in PEP 441) provides an API and command line tool for creating executable Python Zip Applications, which were introduced in Python 2.6 in issue 1739468 but which were not well publicised, either at the time or since.

With the new module, bundling your application is as simple as putting all the files, including a __main__.py file, into a directory myapp and running:

$ python -m zipapp myapp $ python myapp.pyz

---

https://en.wikipedia.org/wiki/J_operator

---

some simple greenfield computer system redesigns:

Project Oberon: https://news.ycombinator.com/item?id=9847955

Plan 9

Urbit

Alan Kay's STEPS project to implement a full OS + apps in under 20k LoC?: http://www.vpri.org/pdf/tr2008004_steps08.pdf

(sorta) http://www.nand2tetris.org/

templeos (was: losethos)

(sorta) http://www.fullpliant.org/

Android

Chromebook

Firefox OS

---

---

"

During the JRuby 9000 dev cycle, we decided it was time to improve the POSIX behavior of our Process and IO subsystems. In C Ruby, IO and Process are implemented directly atop the standard C library functions. As a result, they reflect behaviors often hidden when running Java applications, where those APIs are wrapped in many layers of abstraction. For example, a subprocess launched from Java can’t be read from in a nonblocking way, can’t be signaled, can’t inherit open files and from the parent process, and many other limitations. In short, we realized we’d need to go native to be truly compatible.

JRuby 9000 now uses native operations for much of IO and almost all of Process. This makes us the first POSIX-friendly JVM language, with full support for spawning processes, inheriting open streams, perfoming nonblocking operations on all types of IO, and generally fitting well into a POSIX environment. "

---

 Aleman360 3 hours ago

I work on the Start menu. It's just a UWP XAML app with Models and ViewModels? written in C++/Cx, as are most of the new Shell features and built-in apps--although some of the newer ones, like Maps and Xbox, are in XAML/C#/.Net Native. Even the UI frame of Edge is in XAML, and the new Office UWP apps are too. I encourage everyone here to give UWP apps a shot; we dogfooded the dev platform to ensure it was stable and fast, and XAML really is a pleasure to use. It's come a long way since WPF.

reply

---

---

"If you were to design a new language today, he said, you would make it without mutable (changeable) objects, or with limited mutability." -- van Rossum, paraphrased in https://lwn.net/Articles/651967/

" The GIL

Someone from the audience asked about the global interpreter lock (GIL), looking for more insight into the problem and how it is being addressed. Van Rossum asked back with a grin: "How much time have you got?" He gave a brief history of how the GIL came about. Well after Python was born, computers started getting more cores. When threads are running on separate cores, there are race conditions when two or more try to update the same object, especially with respect to the reference counts that are used in Python for garbage collection.

One possible solution would be for each object to have its own lock that would protect its data from multiple access. It turns out, though, that even when there is no contention for the locks, doing all of the locking and unlocking is expensive. Some experiments showed a 2x performance decrease for single-threaded programs that didn't need the locking at all. That means there are only benefits when three or more threads and cores are being used.

So, the GIL was born (though that name came about long after it was added to the interpreter). It is a single lock that effectively locks all objects at once, so that all object accesses are serialized. The problem is that now, 10 or 15 years later, there are multicore processors everywhere and people would like to take advantage of them without having to do multiprocessing (i.e. separate communicating processes rather than threads).

If you were to design a new language today, he said, you would make it without mutable (changeable) objects, or with limited mutability. From the audience, though, came: "That would not be Python." Van Rossum agreed: "You took the words out of my mouth." There are various ongoing efforts to get around the GIL, including the PyPy? software transactional memory (STM) work and PyParallel?. Other developers are also "banging their head against that wall until it breaks". If anyone has ideas on how to remove the GIL but still keep the language as Python, he (and others) would love to hear about it. " -- van Rossum, paraphrased in https://lwn.net/Articles/651967/

---

example of ClojureScript? AST for "(+ 1 1)":

{:args [{:op :constant, :form 1, :tag number} {:op :constant, :form 1, :tag number}], :children [{:op :constant, :form 1, :tag number} {:op :constant, :form 1, :tag number}], :numeric nil, :segs ("(" " + " ")"), :op :js, :js-op cljs.core/+, :form (js* "(~{} + ~{})" 1 1), :tag any}

http://swannodette.github.io/2015/07/29/clojurescript-17/

---

"Most things in LLVM—including Function, BasicBlock?, and Instruction—are C++ classes that inherit from an omnivorous base class called Value. A Value is any data that can be used in a computation—a number, for example, or the address of some code."

---

" Do you think that it would be possible to create a language with a Hindley Milner type system for the Erlang VM without affecting the power of Erlang semantics?

Not only do I think its possible, I have been planning to do it for a while now, time being the limiting factor. The main problem you will run into is the mismatch between the untyped bits of the Erlang native system and the typed bits of the new language. Dialyzer attempts to solve this through Success Typing, but there may be a better way. Something like what Roy [programming languages that tries to meld JavaScript? semantics with some features common in static functional languages] is doing in its type system or Clojure’s core.typed. I am not sure, but it’s a fun and solvable problem.

"

" BEAM is the only reasonably popular VM that took the language model, in this case Actors, and leveraged that model to make the platform itself more efficient. I find that brilliant. The two major examples of that approach in BEAM are how the Garbage Collector works with the runtime and how IO works.

In many systems, Java included, the Garbage Collector (GC) must examine the entire heap in order to collect all the garbage. There are optimizations to this, like using Generations in a Generational GC, but those optimizations are still just optimizations for walking the entire heap. BEAM takes a different approach, leveraging the actor model on which it is based. That approach basically has the following tenets:

    If a process hasn’t been run, it doesn’t need to be collected
    If a process has run, but ended before the next GC run, it doesn’t need
    to be collected
    If, in the end, the process does need to be collected, only that
    single process needs to be stopped while collection occurs

Those three tenets are one of the primary reasons that Erlang can be a soft-real time system [Elang has a preemptive scheduler that also plays big a part for this]. The fact that the model subsets the work that the GC has to do allows that work to remain small and manageable. Its an impressive achievement. "

--- https://medium.com/this-is-not-a-monad-tutorial/eric-merritt-erlang-and-distributed-systems-expert-gives-his-views-on-beam-languages-hindley-a09b15f53a2f

---

something we should have an annotation for:

https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

" — Built-in Function: long __builtin_expect (long exp, long c)

    You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.
    The return value is the value of exp, which should be an integral expression. The semantics of the built-in are that it is expected that exp == c. For example:
              if (__builtin_expect (x, 0))
                foo ();
    indicates that we do not expect to call foo, since we expect x to be zero."

---

how to prevent this? have a warning for something like __DATE__, or mb don't allow __DATE__ or other impure code in any compile-time or metaprogrammy thing? or mb just not inside conditions in compile-time/metaprogrammy stuff (so that you can still print the date into a log)

" monkeyshelli 5 hours ago

Someone will lose some hair over this

  /* create memory leaks if compiled on April, 1st */
  #define free(x) if(strncmp(__DATE__, "Apr  1", 6) != 0) free(x)

The random ones are just pure evil.

reply " -- https://news.ycombinator.com/item?id=10084898

---

how to prevent this?

cjslep 5 hours ago

From "How to write unmaintainable code" [0], here is a function declaration that changes signature based on how many times the header is #included:

  1. ifndef DONE
  2. ifdef TWICE void g(char* str);
  3. define DONE
  4. else TWICE
  5. ifdef ONCE void g(void* str);
  6. define TWICE
  7. else ONCE void g(std::string str);
  8. define ONCE
  9. endif ONCE
  10. endif TWICE
  11. endif DONE

Granted, it isn't one line long.

[0] https://www.thc.org/root/phun/unmaintain.html (Cert issue shows up on FF unfortunately)

reply

-- https://news.ycombinator.com/item?id=10084840

---

need to be able to do stuff like this with Oot:

grep _expr_ thesis.txt

grep -v _color perl -pe 's/.*{(.*?)}.*/\1/'perl -pe 's/_arrows'xargs -n1 perl -e '$src = $ARGV[0]; $dest = $src; $dest =~ s/.jpg/_color.jpg/; print "mv $src $dest\n";'

mv sdk2_expr_edgeinv_cor_11-57_16x_77332746_389.jpg sdk2_expr_edgeinv_cor_11-57_16x_77332746_389_color.jpg mv sdk2_expr_edgeinvgamma_sag_16_8x_69873475_122.jpg sdk2_expr_edgeinvgamma_sag_16_8x_69873475_122_color.jpg mv robo1_expr_edgeinvgamma_cor_9-53_16x_73521820_404.jpg robo1_expr_edgeinvgamma_cor_9-53_16x_73521820_404_color.jpg

cd images/ish grep _expr_ ../../thesis.txt

grep -v _color perl -pe 's/.*{(.*?)}.*/\1/'perl -pe 's/_arrows'xargs -n1 perl -e '$src = $ARGV[0]; $dest = $src; $dest =~ s/.jpg/_color.jpg/; system("mv $src $dest\n");'

grep _expr_ thesis.txt

grep -v _color perl -pe 's/.*{(.*?)}.*/\1/'perl -pe 's/_arrows'xargs -n1 perl -e '$ARGV[0] =~ /(\d+)x_(\d+)_(\d+)\.jpg/; $scale = $1; $id = $2; $slice = $3; print "download_ish_images_for_sectionNumberRange($id, $slice, $slice, downsampling=$scale, expression_image=True, expression_image_colormap_params=(0.5,1.0,0,256,0))\n"';

download_ish_images_for_sectionNumberRange(77332746, 389, 389, downsampling=16, expression_image=True, expression_image_colormap_params=(0.5,1.0,0,256,0)) download_ish_images_for_sectionNumberRange(69873475, 122, 122, downsampling=8, expression_image=True, expression_image_colormap_params=(0.5,1.0,0,256,0))

---

luismarques 8 hours ago

Try programming with (std.)ranges and (std.)algorithm's. It's something completely refreshing, replacing a mess of loopy code with a clean pipeline of algorithms. The lazy nature of the standard algorithms and the clean syntax you get with the UFCS feature produce some really neat results. Even if you end up not using D any further, it can change your view of programming.

reply

eco 5 hours ago

Yeah, it's a lot like lisp in that regard. I'm glad I learned D even though I don't use it professionally if only because it changed the way I look at some things. The algorithm chaining enabled by UFCS and the range based standard library can lead to some very beautiful code (at least as far as C-family languages go). It also made me painfully aware of how often I copy strings in C++ (string_view cannot come soon enough).

Here's a snippet of code I hacked together in D for a bot to scrape titles from pages of urls in irc messages.

    matchAll(message, re_url)
              .map!(      match => match.captures[0] )
              .map!(        url => getFirst4k(url).ifThrown([]) )
              .map!(    content => matchFirst(cast(char[])content, re_title) )
              .cache // cache to prevent multiple evaluations of preceding
              .filter!( capture => !capture.empty )
              .map!(    capture => capture[1].idup.entitiesToUnicode )
              .map!(  uni_title => uni_title.replaceAll(re_ws, " ") )
              .array
              .ifThrown([]);

It uses D's fast compile-time regex engine to look for URLs, then it downloads the first 4k (or substitutes an empty array if there was an exception), uses regex again to look for a title, filters out any that didn't find a title, converts all the html entities to their unicode equivalents (another function I wrote), replaces excessive whitespace using regex, then returns all the titles it found (or an empty array if there was an exception). There's stuff to improve upon but compared to how I would approach it in C++ it's much nicer.

reply

---

http://www.key-project.org/ recc. by user pron (Lispy guy?) on HN

---

 edgyswingset 2 days ago

Although this isn't OCAML, one thing I ended up missing when writing Haskell was F#'s Active Patterns.

reply

porges 2 days ago

These exist in Haskell as "Pattern Synonyms". Here's a partial translation of some of the F# examples on MSDN to Haskell;

  {-# LANGUAGE PatternSynonyms, ViewPatterns #-}
  pattern Even <- ((`mod` 2) -> 0)
  pattern Odd <- ((`mod` 2) -> 1)
  testNumber x = show x ++
      case x of
          Even -> " is even"
          Odd -> " is odd"
  data Color = Color { r :: Int, g :: Int, b :: Int }
  pattern RGB r g b = Color r g b
  -- NB: this is bidirectional automatically
  printRGB :: Color -> IO ()
  printRGB (RGB r g b) = print $ "Red: " ++ show r ++ " Green: " ++ show g ++ " Blue: " ++ show b
  -- pretend we have functions to and from RGB and HSV representation
  toHSV :: Color -> (Int, Int, Int)
  toHSV = undefined -- implement this yourself!
  fromHSV :: Int -> Int -> Int -> Color
  fromHSV = undefined
  pattern HSV h' s' v' <- (toHSV -> (h', s', v'))
      -- here we explicitly provide an inversion
      where HSV = fromHSV
  printHSV :: Color -> IO ()
  printHSV (HSV h s v) = print $ "Hue: " ++ show h ++ " Saturation: " ++ show s ++ " Value: " ++ show v
  -- demonstrating being able to use pattern
  -- to construct a value
  addHue :: Int -> Color -> Color
  addHue n (HSV h s v) = HSV (h + n) s v

reply

---

great list of things to consider in language design: https://github.com/btrask/stronglink/blob/master/SUBSTANCE.md definitely read the discussion if you read this too, there are some bad ideas in there: https://news.ycombinator.com/item?id=10157018

---

'Cody' a language for describing patterns in code used by the QuantifiedCode?