
Ask HN: If you could only code with one language which would it be? - miloelias
My friends and I are discussing which language we would choose if we only could code in one language for the rest of our lives. Some arguments have been made for c++, SQL, Java, python and JS
======
dagw
Realistically, Python. Not because it's the best, but because it's the only
language that I feel confident will have libraries/bindings for everything I
need. Or as I've heard someone else put it, python is the second best choice
in any situation.

~~~
j-pb
Isn't the java ecosystem more vast though? I found that even though python has
a ton of libs for everything most of them are unmaintained. And I'd rather not
write lots of C bindings myself :/

~~~
dagw
Java is at least a close second. Very generally speaking, I've found that Java
has a slightly better ecosystem when it comes to more 'enterprise' solution,
while python is slightly better on the science and engineering front. Also,
python is the standard scripting language in just about every application I
run into so, if for no other reason, I wouldn't want to give on a python just
because of that.

------
deepaksurti
Common Lisp. Why? [0]

[0]: [http://p-cos.blogspot.in/2014/09/why-i-like-common-
lisp.html](http://p-cos.blogspot.in/2014/09/why-i-like-common-lisp.html)

Common Lisp / Scheme are great to learn about programming languages
themselves. think learning about closures in CL vs in ObjC and you will
realize how simple concepts become awkward and secondarily builds your taste
so you know engineer who prides in knowing C++ complexity is a fucking idiot.

Personally, CL has helped me quickly learn hard subjects (3D graphics),
prototype software for open ended problems, etc etc.

And any given day, give me a language with live editing and updates, I hate
the edit/compile/test cycle.

~~~
xelxebar
Learning a lisp is on my to-do list and I've narrowed it down to guile or
sbcl.

I'm curious what kinds of projects would cause you to reach for common lisp
over scheme and vice versa. Also would be interested in any other thoughts
comparing the two.

~~~
Jtsummers
Either Common Lisp or Scheme are effective introductions to lisp. Both
languages are standardized. But Common Lisp has a large standard library (pros
and cons depending on your tastes and interest in the language).

Scheme has the benefit of some particularly excellent introductory texts (
_Little Schemer_ , _Seasoned Schemer_ , _Structure and Interpretation of
Computer Programs_ , _How to Design Programs_ ). The first two are not free,
but are great introductory texts (and can be used with Common Lisp with some
adaptation, same with the other two), the second two are freely available
online.

Scheme is also a conceptually "purer" functional language than Common Lisp.
Depending on your background and feelings towards other functional programming
languages that may have some appeal to you.

Common Lisp has a comprehensive standard library via the components described
in _The Common Lisp HyperSpec_. With Quicklisp and other things you can easily
add packages to your projects extending your environment to provide support
for nearly anything anyone has ever written a CL library for.

From a technical perspective, Common Lisp can be a more pragmatic language in
many ways. It allows you to drop into base procedural code, or write
functional code. It has a built-in object oriented system (CLOS) that has a
lot of fantastic features. Much of this can be added to Scheme, and may be
available through an SRFI, but is not baked-in. If you're interested in
_implementing_ object systems, Scheme can be a fun language to use for that
purpose.

Setting aside those, another big difference is one that sometimes causes
heated debate, but for me is just a thing to keep in mind. Scheme is a lisp-1,
Common Lisp is a lisp-2 (really a lisp-n). Scheme has one namespace that
everything uses (though you can encapsulate things inside of closures and
such). What this means is that at the top level your functions and variables
share a namespace. If you make a function _f_ and a variable _f_ only one of
them exists. This leads to some cleaner expressions when using a functional
style as you can just use the variable name in the function position. In
Common Lisp you may have to use something like _(apply # 'f some-param)_ when
f is a variable holding a function reference. This is a minor thing, in my
view, but if your intent is to explore the functional side of lisps it can be
nicer to use Scheme. Common Lisp has separate namespaces for functions,
variables, macros, and other entities (I'd say objects but I want to avoid
confusion with the sense of object-oriented programming objects).

Both have module or package systems for organizing projects. Both have good
testing capabilities baked in or that are easy to add on. Both have active
communities (with a decent amount of overlap between them).

~~~
xelxebar
Wow. Thank you for the detailed and thoughtful reply!

Regarding the CL library, I'm inferring that you feel the SFRI modules aren't
as comprehensive as the CL ecosystem. Is that accurate?

Also, what is your experience with the available tooling, performance and
language interop options for each lisp?

Sorry for the 20 questions!

~~~
Jtsummers
Apologies for the late response. I spent the weekend out of town without a
computer.

Here [0] is a list of the various SRFIs. To answer your first question, I'm
going to first digress.

The history of Lisp began in McCarthy's lab with him and his students. As the
language grew in adoption many variants developed, there was no real standard
(as opposed to Ada, Fortran, Algol, and others that developed around standards
groups). Scheme was an attempt at something like a minimal, lambda calculus-
based, lisp. There's more to its history than that, but that sense of
minimalism is crucial to the Scheme approach. Common Lisp was developed in the
80s as a way to develop a common lisp that brought together many of the
academic and commercial variants in use at the time.

Why is that important? Commercial and academic lisps and a standard merging
them was necessarily large. There were a lot of decisions made that look like
over engineering, until you think about the multitude of systems that it had
to run on. Common Lisp's file path handling can understand how any operating
system might present file paths. The DOS/Windows formatted string, a
Unix/Posix path, whatever VAXes do, IBM mainframes, etc. Very very useful. But
not everything made it into the standard, and it hasn't been updated. As a
community Common Lisp implementations do stay near each others' approach when
extending their implementations to account for things like Unicode or
multithreading, but it won't be the same. Some libraries work by creating an
interface and wrapping the implementation specific code behind it, giving you
a more portable way to accomplish your tasks. CFFI [1] is one such interface,
as an example. Common Lisp had to include some functionality so that people
who'd written Maclisp or Starlisp or whatever could port their code with
minimal alterations,

Scheme never aspired to that. And that's where the SRFIs come in. SRFIs aim to
take common behaviors that may have various conflicting implementations by
people over time and provide a consistent interface. Every SRFI is not
available in every Scheme implementation, and some may have portable
implementations written in mostly pure Scheme, while others need to be
tailored to a specific Scheme implementation. This also means, though, that
unless a library is written in pure Scheme (and many are), they are less
portable in the Scheme world than libraries written in Common Lisp.

Chicken Scheme is the one I used the most besides PLT Scheme which developed
into Racket. It has a pretty comprehensive coverage of the SRFIs (or did at
the time, should still) and a good sized set of available libraries (called
eggs [2]).

When it comes to being able to get things done and write a program, both
Scheme and Common Lisp are equally effective in my view. But they do have
differing philosophies in how they grew to be where they are today.

You may have to write more code yourself in Scheme. But that's not always a
bad thing. In Common Lisp I often found a function already existed to do
_exactly_ what I had in mind. I mean, _yes-or-no-p_ [3] already exists in
Common Lisp. It was considered sufficiently common and useful to make it into
their standard. Scheme doesn't have that and wouldn't have that. So it goes to
philosophical differences and differences in the goals of the two communities.

==============

Regarding tooling, I've not spent too much time trying to do performance
profiling. But CL has a lot of that baked in. This is part of its kitchen sink
appeal. It has a really good debugging system built in. You can change the
value that caused an error and resume from that same point. Scheme debugging
is more implementation specific, I generally did it by way of the REPL adding
a line or function call at a time until I found the error.

CL has baked in trace and time functions which can be used for performance
profiling (how often does a function get called, how long does it take to
execute an operation, etc.). For Scheme implementations this will largely be
implementation specific (NB: Can't comment more on this because I didn't try
to use these when I programmed in Scheme).

==============

The FFI story on both is pretty good these days, though in my experience the
FFI side in Scheme was often really good and a central feature in a number of
implementations (both Guile and Chicken Scheme which I used a decent amount).
Calling into C was almost trivial, having C call into Scheme was less trivial
but not hard.

==============

If you'd like a recommendation on where to start: _The Little Schemer_. Nearly
everything in it is portable across Scheme and Common Lisp (with minor changes
due to some differences in syntax). It's an entertaining book and ought to get
you comfortable with the lisp approach to things. From there you'll be able to
start with either Scheme or Common Lisp. IME, it's easy to switch between them
and I don't get tripped up when I do. It's harder to switch between Scheme
implementations for me than between Scheme or Common Lisp due to their often
slightly different handling of certain behaviors (how they handle modules, or
FFI, or something). This won't teach you how to write large programs in a
lisp, but you'll be very comfortable understanding the structure of lisp
functions and source files and be on your way to coding in the large in lisp.

If you have a math/science/engineering/CS background, check out _Structure and
Interpretation of Computer Programs_ and the associated lecture videos. Free,
Scheme specific though you could technically follow along in Common Lisp if
you take the time to understand the differences between the two languages for
some tasks.

Norvig's _Paradigms of AI Programming_ is a great, but non-free, resource if
you want to understand Common Lisp. It is an AI programming text book, but
it's more like 90% AI and 90% Common Lisp (yes, those don't add up).

And I can't believe I forgot about these: _Practical Common Lisp_ [4]. It is
free, and a very good intro to Common Lisp. _On Lisp_ [5], Paul Graham's text
on the subject. Also free and a great introduction to the language. It's very
heavy on using macros which is one of the defining features of lisps in
general, the ability to write code that writes code (metaprogramming, if
you're familiar with Ruby you've likely done some of this before).

==============

[0] [https://srfi.schemers.org](https://srfi.schemers.org)

[1] [https://common-lisp.net/project/cffi/](https://common-
lisp.net/project/cffi/)

[2] [http://wiki.call-cc.org/chicken-projects/egg-
index-4.html](http://wiki.call-cc.org/chicken-projects/egg-index-4.html)

[3]
[http://www.lispworks.com/documentation/HyperSpec/Body/f_y_or...](http://www.lispworks.com/documentation/HyperSpec/Body/f_y_or_n.htm#yes-
or-no-p)

[4] [http://www.gigamonkeys.com/book/](http://www.gigamonkeys.com/book/)

[5]
[http://www.paulgraham.com/onlisp.html](http://www.paulgraham.com/onlisp.html)

==============

I've reread this a couple times now. I hope it's clear and that I got the
details right. Lisp is a great language to learn. Like learning statically
typed functional languages in the ML and Haskell camp, or learning Erlang,
learning Lisp will open your mind to ideas in how to construct programs that
you probably had never thought of or seen before. The lisp community is pretty
good and responsive, you can check out the IRC channels for them, mailing
lists, and comp.lang.lisp is (or was) a pretty good resource (seeing a decent
amount of spam on the front page, but I don't know if that's common or just me
catching it at a bad time).

I can't promise a lot of help, but if you have some more questions you can
contact me (HN name at gmail). I generally answer my email within a day, and
I'll either give you the answer if I have it or point you to resources that
may help. I will admit my non-work programming has been 90% Erlang the past
several years so I'm a bit rusty (and work is 90% C# and 10# C++ so not much
help here either).

~~~
lispm
> common lisp that brought together many of the academic and commercial
> variants in use at the time

Common Lisp was mainly designed to be a common successor to Maclisp, replacing
Spice Lisp, NIL, Lisp Machine Lisp, S-1 Lisp. Those were all relatively
similar Maclisp descendants.

> Commercial and academic lisps and a standard merging them was necessarily
> large.

Common Lisp is large, because it is based mostly on Lisp Machine Lisp (aka
ZetaLisp), which was already large. Which was an expanded version of Maclisp -
which was already large. Lisp Machine Lisp was simply the Maclisp successor
with the most work put in already.

Stuff like pathnames also came from Lisp Machine Lisp, where the Lisp-written
OS interfaced to several outside systems with different pathnames. It was
thought to be useful in portable code, since Common Lisp code should run on
many different operating systems with different file systems.

> Scheme never aspired to that

R6RS Scheme and R7RS Scheme Large were/are attempts to standardize slightly
larger portions of the Scheme language.

------
Grazester
C# I was a noobie programmer at the time and only programmed in C++ and php. I
then experienced what it was like to truly love a programming language after I
was employed to do a tiny project in C#

------
thomascgalvin
I'm a recent convert to the Church of Kotlin.

If you know Java, it takes a week or so before you're comfortable, and after
that it's magical. All of the boilerplate, all of the tiny little frustrations
and bad ergonomics, are just gone.

IntelliJ is a fantastic IDE, too, and I didn't bother picking it up until I
started playing with Kotlin.

Kotlin compiles to JVM bytecode, and it runs everywhere I'm currently
deploying applications. It can be mixed in with existing Java baselines, and
interoperability is almost perfect.

Kotlin also cross-compiles to Javascript, and there's a new Native target,
which I haven't played around with yet, but seems like a decent answer to Go's
statically compiled, platform native, single binary output.

Lastly, there's an experimental feature that allows you to write one source
base and target native, the JVM, and browsers. That finally gives me a single
language that I can run anywhere that isn't Javascript.

~~~
vram22
Is the Native target stable, or experimental as of now?

------
shakna
C, because I care about speed, program size, and multiple CPU architectures.

Or Stackly, a language I've been writing for nearly two years now. Like C,
it's performant, compiles to tiny binaries (it maps fairly close to assembly
under the hood), but unlike C it has a ref-counting GC, compile-time and
runtime type safety.

    
    
        set [hello] fn 'displayln [Hello, World!]
        hello
    

I did used to care a lot more about community adoption or libraries, but less
so today. If you're not dealing with protocols or encryption, and there is no
library, and you can spare a month or two, then writing the library isn't a
hard task. First fortnight to implement, six weeks to fuzz n fix.

But then, I've been forced to work with all sorts of estoric languages in my
work, from PL1 to FORTH to Brainfuck, so my experience is unlikely to be the
norm.

~~~
johnny_1010
[https://github.com/shakna-israel/stacky](https://github.com/shakna-
israel/stacky)

~~~
shakna
'fraid that's something else entirely. That was part of a uni assignment.

Stackly isn't public yet, and probably won't be until I finish the type-
checkers.

------
amerkhalid
I am learning Swift this year. Surprised it hasn't been mentioned yet. I am
hoping to make it is my main language, I doubt if you can live with only one
language forever though.

My reasoning is that this is one language that you can use to write apps for
MacOS and iOS possibly sharing some codebase. It doesn't run on VM, so should
be faster. Swift Playgrounds got me interested in this especially the fact
that it seems to work with a lot of toys like Mindstorms. It might even evolve
to support server side dev. So I see it as decent investment.

Also people in Apple's ecosystem seems to spend more money on apps even with
smaller market share of Apple. And really want to write apps that do something
interesting as I am really bored with another CRUD webapp with pretty UI.

------
quotemstr
What does this question even mean? Give me one language and I'll implement
others as needed. Where do you draw the line between data format, template
system, and "language"?

~~~
dTal
From this perspective, the correct answer is "assembler". Everything else is
just fancy tools to generate that, right?

~~~
xelxebar
Which flavor? GAS, NASM, MASM? Should we go with straight opcodes? And if
we're talking it this far, what CPU architecture? Etc ad infinitum...

------
hackme1234
Python. Its simplicity is unparalleled.

------
sghiassy
JavaScript - Because it’s on the Web, Phones, Server, Embedded Decices, etc
etc.

By having the widest array of hardware devices to build on, I’d have the
opportunity to solve the widest scope of problems.

------
avmich
I've thought about that for some time until it started to feel like a wrong
question.

I usually wanted to code in one language to save learning many languages to an
expert level. Also it felt good to have a uniform code on various levels of
the system - something which today in JavaScript world is called
"isomorphism". Then I realized I'm really doing different things in different
layers, and in a big language I'll perhaps use different parts of the language
- effectively several languages. For a small language I'll probably be
creating necessary constructs first - again, different for needs of different
layers - and then would use those.

Now I think it's better to have the ability to adjust language after the task,
and here Lisps look rather good. Even more, with security in mind I want to
use not only "language suited for the task", but "language minimally suited
for the task", so it's hard to use it incorrectly and easy to reason about
abilities of the particular software layer. Here, again, Lisp-like languages
are a good platform. Some others languages suitable for DSL creation (Haskell?
Tcl?) can also be good.

------
vorg
Which language would I choose if I could only code in one language for the
rest of my life? English, of course. I can encode more meaning in English than
those examples you gave, and that's my criteria. But I wouldn't blame someone
else for choosing C if their criteria was how fast code written in that
language could run on a PC, or Lisp if their criteria was building DSL's
quickly, or Russian if their criteria was communicating with people living in
Novosibirsk.

------
fractalwrench
Kotlin. It has has great tooling with IntelliJ, loads of libraries in the JVM
ecosystem, and Native/JS build targets are in the works. It's also far less
verbose than Java.

------
xelxebar
Sorta hijacking the question here, but I'm curious if anyone here prefers
using some concatenative language. If so, what language (s) and why?

I recently stumbled across
[http://concatenative.org](http://concatenative.org) and my curiosity is
thoroughly piqued.

------
mobilefriendly
PHP, because it is simple, powerful, has bindings for everything, and the
largest community with huge projects like Wordpress and Drupal. I know it
isn't as trendy as python but all of the arguments made so far for python
apply to php as well, and php is older and more widespread.

~~~
pythonaut_16
Python actually predates PHP by quite a bit.

A (non-scientific) look at Wikipedia puts Python's first public release in
1991, and PHP in 1995. But Python's roots actually go back to the late 80s,
while PHP was started and released in 1995. PHP was really originally created
as a collection of helper functions, not a full programming language.

------
juliangoldsmith
Personally, I'd go for Rust.

It can do (most) everything that C can, but is (usually) a lot easier to work
with.

------
vectorEQ
machine code. because you couldn't extend any higher level language if it
needed it, since you wouldn't be able to write assembly >.>. you'd be stuck
with 1 system forever, not being able to make use of any new cpu or hardware
features etc.

------
akmittal
Definitely JavaScript. It is almost everywhere Frontend, Web back-end, IoT,
machine learning. It may not have good reputation for its past but new
JavaScript is quite enjoyable. Being a dynamic language how fast JavaScript
has become always surprises me.

------
dasmoth
If it absolutely had to be one thing for _everything_ (including projects
where I have to work closely with others), JavaScript. For solo stuff
Clojure/script.

But please don’t let it come to this. I’m happiest as a polyglot.

------
pmiri
If this is a desert island-type scenario, haskell.

If I had actual time limits, python.

------
jedisct1
Ruby. By far the language I'm the most productive with.

------
earenndil
Lisp, not _necessarily_ because it's good, but because it's easier with reader
macros to transform another language into it as needed.

------
j-pb
Clojure. Give me immutability or give me death :D

------
brettkromkamp
Clojure. Almost infinitely extensible.

------
bllguo
SQL?? What is the argument for that?

------
k120
Lisp. With metaprogramming technique I can add any modern paradigm and
language features.

------
xstartup
I've most extensive experience in Python but I choose Ruby. Then Rust, finally
Go.

------
bionsystems
C so I can work on most of the stack (and why not write my own languages if
needed).

------
alt3red
Python, because it's what I know best and what makes sense to me.

------
romanovcode
C#

It has all you mentioned:

\- C++ (Strong OOP + Static typing)

\- SQL (LINQ)

\- Java (Well, no comment here)

\- JS (dynamic, async/await)

~~~
dlahoda
\- C (native pointers, ref parameters and returns, structs)

~~~
romanovcode
Yeah, forgot about that. It's a new feature of 7.2 AFAIK.

------
naikke
Ruby

------
malyk
Ruby

------
deadmetheny
Perl.

------
mankash666
C

------
codegladiator
golang

