oh-lang is motivated to solve some consistency problems in other programming languages.
in most languages, primitive types have different casing than standard classes. e.g.,
in earlier versions of oh-lang, we experimented with
in addition,
oh-lang does use
although
†: note that oh-lang infers types where possible, so
P.S. earlier versions of oh-lang also distinguished function case from variable case. e.g.,
in most languages, primitive types have different casing than standard classes. e.g.,
i32 vs. String. there is no good reason for this. it makes choosing a "default name" for your type impossible, which is something that oh-lang wants to do to support quick declarations. in oh-lang, i32: 5 evaluates to i32: #i32 = 5 because the variable name i32 matches an existing type name #i32.† this is especially important for function arguments, where typically in most languages like Rust you have redundancy like fn my_function(my_class: MyClass), which becomes my_function(my_class:) in oh-lang.
in earlier versions of oh-lang, we experimented with
PascalCase and SCREAMING_SNAKE_CASE for type names. these were eventually abandoned in favor of #snake_case mostly for readability. separating logical words in your identifiers by underscores makes long names easier to read, and similarly for lowercase vs. uppercase. try to read each of these quickly -- MyLongNameForAClassThatDoesX vs. #my_long_name_for_a_class_that_does_x vs. MY_LONG_NAME_FOR_A_CLASS_THAT_DOES_X-- and you'll see what i mean.
in addition,
PascalCase for types and camelCase for variable names works to give default names, but one other strike against it is that it makes refactorings slightly harder. if you are changing type #whatever_type to #new_type, the regex for oh-lang is simply whatever_type/new_type/g whereas for the pascal/camel-case combo you'd need to do two separate passes whateverType/newType/g and WhateverType/NewType/g or risk more complicated regexes.
oh-lang does use
SCREAMING_SNAKE_CASE for namespacing, so capital letters are ignored when determining the type for something. for example, OPERATOR_token would try to be type #token. we could have reversed this logic (i.e., using SCREAMING_SNAKE_CASE for the type not the namespace), but that would have made the code look angrier more of the time.
although
#type_name has a bit of overloading in oh-lang with # a comment, we see this as a net positive because types are similar to commenting your code. editors can help to make the two visually distinct as well. using # it also makes it easy to create an inline data structure type, e.g., #[x: #f32, y: #f32], which is grammatically easier for oh-lang to distinguish as a class type than omitting #.
†: note that oh-lang infers types where possible, so
my_unique_variable_name: 5 would try to look up the type #my_unique_variable_name and initialize it with 5, but failing to find the class would fallback to the default type of 5, which is a big integer. i.e., in this case you'd get the equivalent definition my_unique_variable_name: #int = 5.
P.S. earlier versions of oh-lang also distinguished function case from variable case. e.g.,
my_variable vs. my_function_. this made it easy to create a default variable name for function, e.g., max: max_(3, x), but we realized we can just overload variables and functions like max: max(3, x) and we know we're using a function or variable by if we're using () or not.
Comments
Post a Comment