proj-oot-ootNotes27

rthomas6 4 hours ago [-]

One "non-programmer" perspective here: Python is the new Perl, except it's fast to read AND write. In Python it's fast to do ...everything. I'm an electrical engineer by trade, and Python gets used a lot.

    import csv
    with open(filename) as csvfile:
        csvreader = csv.DictReader(csvfile)
        data = list(csvreader)

Bam, an array of dictionaries with the data in them, indexed by column name. With listcomps, whatever I need to do will only take a few more lines. And it's this easy for almost any data format. There will be a widely used library for me to `pip install`.

I don't have to do any compile steps. I don't have to use a special IDE. I don't have to think in objects and state-passing and all that BS (but I can if I want to!). I don't have to search for some arcane library. I don't have to know a magic build sequence. I don't have to edit config files. I just make cool shit really fast. It runs slower, but for most things I use it for, I don't care if it takes 10 us or 10 seconds. I just want to make it work.

reply

---

uvtc 6 hours ago [-]

> Looking forward to the "why" post. Glad that they mentioned that they'll be publishing that soon.

I think the "why" is because, for many users:

Python has its own set of problems, but it hits all those marks except for the last one. So, it's gotten quite popular.

reply

tim333 4 hours ago [-]

A lot of people like the Python syntax. It has to be about the most readable of all computer languages.

reply

---

zimablue 17 hours ago [-]

I moved from my last job (mostly C#/vba, front office finance)to a new role (python, data guy at hedge fund).

Doing data stuff and simple web services is absurdly more straight forward in python, the main things I miss (weaknesses of python to C# and I'm guessing java):

nice parallel options (I know several options exist but haven't found any of them as easy to get into as C# async/await, GIL is the problem i guess)

the django database layer doesn't do smart diffs in the same way as .net db projects (in .net it's smart enough to actually look at your code schema vs the database and work out how to roll forward/back, in django it's just using a combination of your code schema and a table describing what has and hasn't been rolled out yet, making everything a bit scarier and tougher if anything goes wrong. I dunno if SQLAlchemy does this.

edit: also I once read a HN comment that a problem at the heart of python is that block-syntax forces you into having only trivial inline lambdas, after writing it for a while I think they might have been right

reply

mixmastamyk 24 minutes ago [-]

Trivial lambdas make Python more readable than highly nested languages.

reply

---

mirekrusin 1 day ago [-]

This is the first time I can see Zig lang [1]. (Self-proclaimed?) C successor with manual memory management, ironed out edge cases, new take on error handling (that resembles well written error handling in C), generics, compile time reflection/execution (macros?), import .h works directly, exporting to C works directly, nullable types etc... all sound quite interesting actually. Anybody has experience/comments on the Zig lang, please?

[1] http://ziglang.org/

reply

---

" ES2015 (also known as ES6), the version of the JavaScript? specification ratified in 2015, is a huge improvement to the language’s expressive power thanks to features like classes, for-of, destructuring, spread, tail calls, and much more. "

---

 kbenson 4 hours ago [-]

> So a CoffeeScript? => is now output as =>

Wait, using the arrow function notation doesn't bind this, arguments, super, or new.target[1] in javascript, as opposed to the normal function syntax. Not being a user of coffeescript, did coffeescript not do that already, or did they also throw in code to change that in the generated code?

madeofpalk 4 hours ago [-]

Coffeescript's => binds this. Javascript's => also binds this (more or less)

Seems to map fairly well conceptually.

reply

---

" Any decent PL course would emphasize the first-class-everything (procedures , obviously), lexical scooping for proper closures, strong but dynamic typing (no implicit coersions) etc. No matter which sect one belongs to - ML or Scheme - these are universal fundamentals, the well-researched foundation.

PHP/Javascript coders usually do not understand the principles and implications behind languages they use. Otherwise they would develop a healthy aversion, like to a tasteless, vulgar porn.

Sane people with PL background would use a dialect of Scheme as a DSL (the numerical tower and all the nice things) or at least Lua (because packers are afraid of parenthesis and see nothing behind of them).

Actually, Scheme (or a simplified dialect such as the one inside Julia - flisp) would be almost ideal choice for financial DSLs.

"

---

 serhei 84 days ago [-]

It sure makes me wonder if Ethereum would do better with a less forgiving programming language. The fact that the syntax resembles Javascript is not reassuring, neither is the fact that the very first code snippet in "Solidity By Example" [1] is littered with comments like this:

        // Forward the delegation as long as
        // `to` also delegated.
        // In general, such loops are very dangerous,
        // because if they run too long, they might
        // need more gas than is available in a block.
        // In this case, the delegation will not be executed,
        // but in other situations, such loops might
        // cause a contract to get "stuck" completely.

---

ghthor 84 days ago [-]

What would be the complications in providing a transpiler for pact into Solidity?

spopejoy 84 days ago [-]

It's possible, but impractical:

The biggest issue facing Solidity developers today is the sheer cost of best practices: ensuring you handle overflows right (ie don't use math primitives but call an approved function), planning for upgrades/data export, you name it: you have to use that code and pay that gas. The environment really needs to provide a lot more "free" functionality than it does today to change this reality.

---

spopejoy 83 days ago [-]

We haven't seen the use-case yet where the (signature,payload) tuple is not isomorphic to a transaction. Yes, in the case of multiple, distinct payloads, you'd have to break those into separate transactions, but that seems like a very specific use-case that doesn't sound very "transactional".

Pact's philosophy sees a blockchain as a special-purpose database, for distributed transactions, so it's not designed for many "normal" database cases, namely bulk operations, searches, heuristics, etc. The use case of accepting multiple signed payloads sounds suspiciously "batchy" to me. Also, Pact is "success-oriented": we see failures like a bad signature as something that should fail your tx only. This is a way of avoiding dicey control-flow logic.

So, if a single payload is what you need the signatures on, you simply design your contract API/function call to have the specific function to handle that data (store it in the database, whatever), and let the environment check the signature.

EDIT: Pact is actually `([Signature],payload)` -- ie, you can sign the same payload multiple times

woah 82 days ago [-]

Signing the same payload multiple times would work for my use case (channels). I also need to accept transactions signed by at least one of two keys. I suspect this might be possible too. However, I can imagine that anything more complicated would go outside of the system you have designed. I haven't had the chance to learn your language, but I would be wary about it either being too limited for edge cases that most real world stuff is going to have, or turning into a "universal framework" antipattern.

spopejoy 82 days ago [-]

> I also need to accept transactions signed by at least one of two keys.

Keysets are designed for precisely this; what's more this rule can now be persisted.

> anything more complicated would go outside of the system you have designed.

Always a possibility of any PL, especially running in a blockchain. Pact makes less assumptions about use cases than most however. It's imperative, allows functions and modules, and offers a database metaphor. That handles a fair number of things.

---

xg15 83 days ago [-]

Also, I think "hard to write" is meant as "require that critical or dangerous details are written explicitly; if a feature adds convenience for writing at the expense of reading, it should be avoided". (Type inference, overloads and reflection come to mind)

I think (hope) that no one is advocating making a language verbose or complex for it's own sake.

kronos29296 83 days ago [-]

Like Rust? Rust does most of those things wrt explicit dangerous behaviour.

xg15 83 days ago [-]

Exactly.

---

MicahZoltu? 66 days ago [-]

There is an EIP that is slated to land in the upcoming hardfork that adds an EVM opcode for effectively "const" call that is enforced by the runtime: https://github.com/ethereum/EIPs/pull/2

---

variables should be local (not global) by default.

functions and fields should be private (not public) by default.

---

kbenson 68 days ago [-]

...PHP at that time was a mix of some good ideas (ease of deployment) with some horrible ones (register globals on by default is unexcusable), and some poor planning. We all lived with the fallout of that for a very long time.

---

" We still shouldn't give up to look for better ways to code, but I think the better ways are easier to use programming languages that preserve the general purposeness of programming, better interactive environments (like F# interactive, Python REPL, etc.) and helpful syntax highlighting and better code annotation systems. Maybe live rendering of markdown and explanatory pictures in the IDE would be a helpful first step. "

--

"

The ID is composed of two parts: a millisecond time and a sequence number. 1506871964177 is the millisecond time, and is just a Unix time with millisecond resolution. The number after the dot, 0, is the sequence number, and is used in order to distinguish entries added in the same millisecond. ... The millisecond part of the ID is obtained using the maximum between the current local time of the Redis server generating the ID, and the last entry inside the stream. So even if, for instance, the computer clock jumps backward, the IDs will continue to be incremental. In some way you can think stream entry IDs as whole 128 bit numbers. "

---

yongjik 1 day ago [-]

After being exposed to several declarative tools during my career, I must say they age poorly: make, autoconf, Tensorflow, and so on. They may start out being elegant, but every successful library is eventually (ab)used for something the original authors didn't envision, and with declarative syntax it descends into madness of "So if I change A to B here does it apply before or after C becomes D?"

At least Tensorflow isn't at that level, because its "declarative" syntax is just yet another imperative language living on top of Python. But it still makes performance debugging really hard.

With PyTorch?, I can just sprinkle torch.cuda.synchronize() liberally and the code will tell me exactly which CUDA kernel calls are consuming how much milliseconds. With Tensorflow, I have no idea why it is slow, or whether it can be any faster at all.

reply

rkangel 1 day ago [-]

I believe that make's declarative is not the cause of it's problems at all - it's poor syntax and lack of support for programming abstractions is what makes it clunky to use.

Something like rake, which operates on the same fundamental principles (i.e. declarative dependency description) but using ruby syntax has aged better.

reply

eru 1 day ago [-]

Indeed. Getting these text based configuration tools work requires a lot of experience in language design.

Lots of tools become accidentally Turing complete, like Make. You need to plan these things from the start. If you want any computation possible at all, you need to be extremely vigilant, and base your language on firm foundations. See eg Dhall, a non-Turing complete configuration language (http://www.haskellforall.com/2016/12/dhall-non-turing-comple...).

If you are happy to get Turing completeness, you might want to write your tool as an embedded DSL and piggy-bank on an existing language, declarative or otherwise.

reply

acjohnson55 1 day ago [-]

SBT in the Scala world would also fit this description.

reply

---

" UTF-8 has some really useful properties:

    It’s backwards compatible with ASCII, which never used the highest bit.
    Sort order is preserved. Sorting a set of code point sequences has the same result as sorting their UTF-8 encoding.
    No additional zero bytes are introduced. In C we can continue using null terminated char buffers, often without even realizing they hold UTF-8 data.
    It’s self-synchronizing. A leading byte will never be mistaken for a continuation byte. This allows for byte-wise substring searches, meaning UTF-8 unaware functions like strstr(3) continue to work without modification (except for normalization issues). It also allows for unambiguous recovery of a damaged stream.

" -- [1]

---

one nice thing about pass-by-reference in Python, as opposed to pass-by-value, is that you can often factor a chunk of code out into a separate subroutine without worrying that updates to composite data structures won't be preserved (as would be the case with pass-by-value); with pass-by-reference, any updates to composite data structures occur whether or not they are encapsulated in a subroutine.

eg the following:

blah... try: input_rows[row_to_process_idx] = readers[row_to_process_idx].next() except StopIteration?: input_rows[row_to_process_idx] = None blah...

is equivalent to this:

def advance_to_next_input_row(row_to_process_idx, input_rows, readers): try: input_rows[row_to_process_idx] = readers[row_to_process_idx].next() except StopIteration?: input_rows[row_to_process_idx] = None

blah.. advance_to_next_input_row(row_to_process_idx, input_rows, readers) blah..

---

woah here's a pretty good argument for Scheme over Common Lisp imo: you can't just do

> (define (adder n) (lambda (x) (+ x n)))

adder

> ((adder 3) 5)

instead if you have a dynamically computed function like that you must call it with 'funcall':

" “How do I write a function that returns a function?” is a typical question asked by people who have learned Scheme before they started with Common Lisp. In Scheme, they were accustomed to be able to do things like this:

> (define (adder n) (lambda (x) (+ x n)))

adder

> ((adder 3) 5)

8 ... in Common Lisp...

we can’t use it in the same way we would use it in Scheme:

CL-USER> (adder 3)

  1. <Interpreted Function "LAMBDA (N)" {485FFE81}>

CL-USER> ((adder 3) 5) In: (ADDER 3) 5 ((ADDER 3) 5) Error: Illegal function call.

Here is why: CL has different namespaces for functions and variables, i.e. the same name can refer to different things depending on it’s position in a form that’s evaluated:

CL-USER> (boundp 'foo) NIL CL-USER> (fboundp 'foo) NIL CL-USER> (defparameter foo 42) FOO

...

To simplify a bit, you can think of each symbol in CL having (at least) two “cells” in which information is stored. One cell - sometimes referred to as its value cell - can hold a value that is bound to this symbol, and you can use boundp to test whether the symbol is bound to a value (in the global environment). You can access the value cell of a symbol with symbol-value.

The other cell - sometimes referred to as its function cell ...

Now, if a symbol is evaluated, it is treated as a variable in that it’s value cell is returned - see the line marked with * above. If a compound form, i.e. a cons, is evaluated and its car is a symbol, then the function cell of this symbol is used - see the line marked +++ above.

In Common Lisp, as opposed to Scheme, it is not possible that the car of the compound form to be evaluated is an arbitrary form. If it is not a symbol, it must be a lambda expression, which looks like

(lambda lambda-list form*)

This explains the error message we got above - (adder 3) is neither a symbol nor a lambda expression. But, you might ask, how do we use the function object that is returned by adder? The answer is: Use funcall or apply:

;;; continued from above CL-USER> (funcall (adder 3) 5) 8 ... "

-- [2]