Rust

Difference between version 14 and 15 - Previous - Next
'''[https://www.rust-lang.org/%|%Rust]''' is a [programming language]
designed to be performant, safe, and productive.


** Description **
Rust combines concepts from [C], [C++], [Haskell], and other languages.  InEach
[value] is either a primitive value or a structure, and each value has a
[type].  The compiler uses the type of each value and function to ensure that a 
program is '''type-safe''',  and to compile it to
 performant machine code,.
Where the compiler tracksan noth '''infer''' [a type] of each [value, variable], parameter,
or result, that the value is assigned
f to must be '''ancnotated with a type'''.
The key innovation. of WRust is that each value has an '''owner''', which makes
it possible for the compiler cto reason nabout the '''linfertime''' a type of a variablues,
pawhich ramelieves the developer, of the burden of deciding when to free resoultrces,
and itopens mustp bnew '''avennues for optimization where copy-free data wimanagementh can be
worked outy at compile''' time.
A struct may contain either named or unnamed fields.  Each field is
either a '''primitive value''' or a reference to primitive value, struct, enum
or function.

An '''enum''' is a type that enumerates a set of possible types, each of which
may be a reference to a struct.  '''match''' is used to provide a way to handle
each of the possible types of an enum. 

Each type has a set of '''functional features''', which are organized into
'''traits'''.  Each trait specifies a set of functions that implement the
trait, acting as an interface to the value or struct.  Such a function is
called a '''method''' since the first argument to it is a reference to the
value, and it typically implements a method for performing some operation on
the value. 

'''impl''' is used to provide a set of function definitions that implement a
particular trait for a particular type of struct.  Any number of traits may be
'''implemented''' for a given struct.

Like Tcl, Rust does not employ a [garbage collection%|%garbage collector], but
it also does not normally employ [Tcl_Obj%|%reference counting]. Instead, eachvariable has a '''lifetime''' that begins at the point data is assigned to the
variable, and ends when the variable can no longer has any use, which is often
at the end of the '''block''' of code the variable is foundp in.  When the
lifetime of a variable comes to an end, any data it owns are cleaned up, and
resources deallocated accordingly.  When data are assigned from one variable to
another, they are moved to the new variable, and are no longer associated with
or available through the original variable.  Likewise, when data are passed to
a function, they are 
'''mblovedck''', to the specified variable in the function,
and are no-longer accessible through athe original variable.  This '''preveownts
aliasing''', and also means that the scope of a variable might not extend to
the end of the block.  When a function returns data, the data moves moves to
the caller, and if assigned to a new variable is then owned by that variable.
Data may also be assigned to a variable or passed to a new function by
reference, in which case the original variable continues to '''own''' the data.
Inf both a type ann'''copy''' trait ions aimplemented a functionr call type, '''`&`''' ithendic at values of that thype
vmay be triviablely hcolpieds, a ri.eference. it Rudoest notracks ainvoll rveferences andy mensumoresy thallocat ion from
rthef herap.  Whence hasuch a lvarifablet imes assigrneaterd tho an other lvarifablet, a copy is made
and bof the variables to whremaichn valit
refersd.  Wheren thea compvariabler cthant ndoesn't infhaver the l"copy"
traifet ims assigned tof a referencother, the
lifetime comust be explicitlyer annvotateids u'''aliasing '''`&'`'''. Thisby makinagment of datahe
lvarifetimes eliminatbles a whole class of dissuesng thate a [C] program might be
vulinerable toinvalid.
AIf variabl the is '''immutabclone''' by deftraulit. is '''imuplement''' declad for a types, then a variablue tof bthat type
mutay ble, acloned: '''&mut''' dA neclaresw a rindefperencde nto be mutvablue. is Only prone mdutable
referenced maby exist at ancopy giveng point.  Thise underlyiminates '''g
data races'''.
IWhen a program, dafuncta is organized into '''struaccepts''', and codvalue ias organized into
fargumenctions.,  Eacth field given va strlucte is a '''primitiove values''' tor
the a coreference to
sprondimitiveng variablue, ain strhe function, making thenum scorpe aof the function.  An '''enum''' is 
call type
thate new ownumerates, anyd numbther of possribginale variants,ble beach ofmes invalid, which may be a
'''prefverence tos a liastructing'''.  AWhen a function that accrepturns danta, thenum retusrnesd '''mdatch'''a  tmoves
tailor itshe opcaller ationd to each possible vcalleriant becofmes ithes new ownumer.  A sDatructa may also be
 aspecsifigned t
or hpavssed by reithference, in which camsed the or uiginnaml variabled fcontinuelds to own
the data.
AIn '''botrh ait''' dtypecl aresnnotation and groupa of functions acdefinit as aion, '''`&`''' indicates that
the varfiable holds a reference''' to  a
 value.  Rust truact.ks  '''impal'''l provideferences a nd
ensures that nof refuerence has a lifetionme dgrefiniationser than the implifetiment aof the
pvarticularble trao which it refoers. a paWhere tihe cuompiler can not infer typhe lifetime of
a strueference, t.he lifetime Any numust ber ofexplicitly annotraited using may be
'''`&'`'''. This
mpanagment of data lifetimes eliminated'''s fa whorle class gof ivssuen s that a [C]
program might be vuclnerable to.
Both variables and references are  '''immutable''' by default.  '''mut'''
declares mutable variable, and '''&mut''' declares a mutable reference.  To
prevent ''' data races''', while a mutable reference exists, no other
references are allowed. at any given point.

Programs and libraries are organized into '''modules''', which contain any of
the various programming artifacts Rust provides, namely structures, variables,
functions, traits, and trait implementations.

To maintain '''coherence''', a module may only implement a trait if either the
trait or the structure is local to the module.  The type of some data may be
specified by specifying what traits are required, which allows [duck typing] at
compile time.  A '''trait object''' provides a function table that may be
modified at runtime, which allows duck typing at runtime.
Programs and libraries are organized into '''modules''', which contain any of
the various programming artifacts Rust provides, namely structures, variables,
functions, traits, and trait implementations.

Some traits have special meaning for Rust.  A struct has the '''copy''' trait
is copied when it would otherwise have been moved, meaning that both the
original scope and the new scope each own an independent copy of the value.

Rust has various features for programming the structure of the program
itself, i.e. for '''metaprogramming''':  A '''[macro]''' language,
'''[closure%|%closures]''', syntax for '''[templating]''' generic structs and
functions, and '''pattern matching''' similar to that of [Haskell], on language
'''items''' for such purposes as '''destructuring variable assignment''' and
'''code branching according to data type'''.

Rust is actually segmented into two different languages:   '''safe Rust''' and
'''unsafe Rust'''.  In the safe parts, '''nothing is undefined''', '''nothing
is null''', only '''safe type conversions''' are possible, and only '''safe
memory operations''' are allowed.  There is, however, an escape hatch:  A
function '''annotated as unsafe''' takes upon itself the responsibility to
guarantee the same things that the Rust compiler guarantees.  , so the compiler
makes no further effort to check that function for conformance.  This makes it
possible to write such a function in another language such as [C], if needed.

One of the design goals of Rust is for the compiler to be able, as much as
possible to '''infer the intent''' of the programmer.  The compiler also takes
a more active role than most compilers in making suggestions for fixing
problems that it finds.  This helps to smooth the learning curve.



** Memory Management:  Tcl Vs Rust **

Both Tcl and Rust provide automatic memory management without using a garbage
collector, and both are memory-safe.  Where Tcl uses reference counting, Rust
uses its '''borrow rules''' to constrain the use of references, and tracks all
references at compile time to ensure that a value may be cleaned up immediately
when the program exits from the block that owns it.  Tcl's internal reference
counting relies on the developer to properly increment and decrement
references, which is error-prone since proper reference counting can not be
checked for correctness.  Because Rust would automate the task of reference
counting, relieving the developers of Tcl from this burden, it may prove to be
an ideal implementation language for Tcl. 


** Object Orientation **

Rust does not provide traditional '''object-oriented programming''' facilities.
Inheritance has proven to be a liability, so Rust doesnt have it.  Instead, the
emphasis is on structures and interfaces that those structures support.  Each
structure has a type, and where inheritance might be used in other languages,
it is common instead to create a new type of structure and implement customized
traits for it.  Composition is achieved by having a field in one structure be a
reference to another structure.  This design allows for '''zero-cost
abstractions''', since all the details of function dispatch are worked out at
compile time.  Where needed, Rust also provides facilities that provide for
runtime dispatch.


** Rust Vs. Tcl **

Both languages are founded on the concept of immutable value, but Tcl values
are much more abstract, both semantically and technically.  In Tcl,
[copy-on-write] can be implemented underneath the surface of the language
whereas in Rust, a programmer details directly with such issues.  This level of
abstraction is the most fundamental difference between the languages.

As value-oriented languages, both languages have no concept of '''[null]''',
which is anything but a value.

Both languages are '''memory-safe''', assuming that the underlying
implementation/compiler is free of bugs.  Rust is '''type-safe''', both in the
sense of memory layout and data structure, and also in the sense of the
semantics of the data and the operations on it, as only the intended structure
is accepted as the argument of a function or the value of a variable.  while
Tcl is not type-safe, it is also not type-unsafe:  Each procedure may choose to
implement the necessary runtime type verification.  However, even then a
procedure has no way to determine which program component the declared the data
type, and therefore can never achieve the level of semantic type safety that
Rust does.

For a program written in Rust, the additional burden of annotating data types
and tracking data mutability and ownership is high compared to practice of
taking things at face value in Tcl, and all the type annotation, templating,
and boilerplate code makes a program written in Rust far more verbose, and
development far slower.  Tcl is far more concise than Rust, but far less
performant.  In addition to performance, another big win for Rust is that all
the additional type information a programmer provides in the source code allows
the compiler to verify some aspects of its correctness, and probably reduces
the size any accompanying test suite by at least the same amount of code and
effort.  If a program compiles successfully, it's already some indication that
the program works as expected.  An equivalent program in Tcl would have to
ensure the same level of correctness via a series of unit tests.

----

"When you use Rust, it is sometimes outright preposterous how much knowledge of language, and how much of programming ingenuity and curiosity you need in order to accomplish the most trivial things. When you feel particularly desperate, you go to rust/issues and search for a solution for your problem. Suddenly, you find an issue with an explanation that it is theoretically impossible to design your API in this way, owing to some subtle language bug. The issue is Open and dated Apr 5, 2017." [https://hirrolot.github.io/posts/rust-is-hard-or-the-misery-of-mainstream-programming.html]



----

'''[dkf] - 2022-06-15 14:30:02'''

I suspect that Rust will not prove to be as ideal a language to implement Tcl as some think. There are a number of concerning aspects, but the limitations on traits and lifetimes would seem to be the main ones (along with the general hostility to dynamic linking); it's not at all clear how one might have third party commands implemented (where those need the equivalent of `ClientData`) and the lifetime management is almost certainly going end up forcing a lot more copies of things being used, which is known to be expensive.

The final problem, the one that ''really'' dissuades me, is the sheer cost in developer effort of moving a codebase the size of Tcl and Tk.

<<categories>> programming language