Tya v0.19 Specification

This document is the specification for Tya v0.19 after v0.18 module-style standard APIs and minimal global built-ins.

Theme

Tya v0.19 adds predicate names.

A function or method name may end with ? when the callable answers a yes/no question. Such a callable must return a boolean value.

Goals

Included in v0.19

v0.19 includes all v0.18 behavior and adds:

Not Included in v0.19

v0.19 does not include:

Predicate Function Names

A function name may end with ?.

empty? = values ->
  len(values) == 0

print empty?([])

The base name before ? follows the normal function naming rule.

Allowed:

empty? = values -> len(values) == 0
has_name? = user -> dict.has(user, "name")
_internal? = value -> value == nil

Forbidden:

Empty? = value -> true
empty_? = value -> true
empty?? = value -> true

Predicate names should not repeat the predicate meaning with an is_ prefix when the shorter base name is clear.

Preferred:

nil? = value -> value == nil
empty? = values -> len(values) == 0
active? = user -> user["active"] == true

Avoid:

is_nil? = value -> value == nil
is_empty? = values -> len(values) == 0
is_active? = user -> user["active"] == true

has_ is still allowed when it names possession rather than predicate syntax.

has_name? = user -> dict.has(user, "name")

Predicate Methods

Instance methods may end with ?.

class User
  init = name ->
    @name = name

  named? = ->
    @name != ""

user = User("komagata")
print user.named?()

Class methods may also end with ?.

class User
  @@enabled = true

  @@enabled? = ->
    @@enabled

print User.enabled?()

Private predicate methods use the existing private naming rule with a leading underscore.

class User
  _valid_name? = name ->
    name != ""

Predicate Module Functions

Module function names may end with ?.

module path
  absolute? = value ->
    string.starts_with(value, "/")

Use the predicate through normal module member access.

import path

print path.absolute?("/tmp/memo.txt")

Standard modules may use predicate names when the result is boolean.

import array
import dict
import value

print array.empty?([])
print dict.has?(user, "name")
print value.nil?(result)

Boolean Return Requirement

Every call to a predicate function or method must return a boolean value.

ready? = ->
  true

print ready?()

Returning any non-boolean value is an error.

name? = ->
  "komagata"

print name?()

The call to name?() is invalid because the function returns a string.

This check is performed when the predicate call returns. Tya remains a dynamic language and v0.19 does not add static return type inference.

Syntax Boundary

? is part of the identifier only when it appears at the end of a callable name.

Allowed callable names:

empty?
has_name?
_internal?

Names that are not callable declarations cannot end with ?.

active? = true       # invalid
class User?          # invalid
module user?         # invalid
@active? = true      # invalid
@@enabled? = true    # invalid as a class variable

The following are still ordinary calls and member calls:

empty?()
user.active?()
User.enabled?()
array.empty?(values)

Diagnostics

v0.19 implementations should report source-oriented errors for:

Diagnostics should mention the predicate name and the actual returned value kind when available.