{"id":33180734,"url":"https://github.com/mndrix/func","last_synced_at":"2025-11-20T21:04:47.203Z","repository":{"id":6586714,"uuid":"7829149","full_name":"mndrix/func","owner":"mndrix","description":"Apply and compose functions in Prolog","archived":true,"fork":false,"pushed_at":"2016-10-27T19:08:37.000Z","size":67,"stargazers_count":19,"open_issues_count":9,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-18T20:35:52.160Z","etag":null,"topics":["functions","prolog"],"latest_commit_sha":null,"homepage":null,"language":"Prolog","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mndrix.png","metadata":{"files":{"readme":"README.md","changelog":"History.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-01-25T21:46:10.000Z","updated_at":"2023-09-11T13:16:09.000Z","dependencies_parsed_at":"2022-09-13T03:01:08.139Z","dependency_job_id":null,"html_url":"https://github.com/mndrix/func","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/mndrix/func","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mndrix%2Ffunc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mndrix%2Ffunc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mndrix%2Ffunc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mndrix%2Ffunc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mndrix","download_url":"https://codeload.github.com/mndrix/func/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mndrix%2Ffunc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285512106,"owners_count":27184309,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-20T02:00:05.334Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functions","prolog"],"created_at":"2025-11-16T04:00:23.089Z","updated_at":"2025-11-20T21:04:47.198Z","avatar_url":"https://github.com/mndrix.png","language":"Prolog","funding_links":[],"categories":["Development"],"sub_categories":[],"readme":"# Synopsis\n\n    :- use_module(library(func)).\n    main :-\n        % create a Plus3 function by composing three others\n        Plus3 = succ of _+1 of plus(1),\n        call(Plus3, 1, 4),\n        format('~s world~n', [atom_codes $ hello]).\n\n# Description\n\nThis module allows one to apply ($/2) and compose (of/2) terms as if\nthey were functions.  One often uses predicates as these functions,\nbut one can define function behavior for arbitrary terms.  See\n\"What is a function\" and \"Defining functions\" below.\n\nWhy? Prolog predicates are more powerful than functions, but sometimes\nthe syntax is awkward or requires meaningless effort from the\ndeveloper (generating and maintaining intermediate variable names and\ngoals).  Using library(func) often results in more succinct, clearer\ncode.  For example, the use of atom_codes/2 in the Synopsis above.\n\nAt compile time, library(func) converts function application and\ncomposition into standard predicate calls.  There should be no\nperformance penalty and one can still use nondeterminism.\n\n# What is a function?\n\nFor our purposes, a function is any term which can be converted into a\npredicate call that accepts input in a single variable and produces\noutput by binding a single variable.  The following sections describe\nterms which library(func) can natively treat as functions.  See\nfurther below for instructions on defining function behavior for\nadditional terms.\n\n## Predicates as functions\n\nAny predicate whose final argument can be viewed as an \"output\" and\nwhose penultimate argument can be viewed as \"input\" can be used,\nwithout modification, as a function.\n\nFor example, succ/2 can be seen as accepting an input as the first\nargument and producing an output, in the second argument, that's one\ngreater.  Similarly, the term `plus(3)` can be seen as a predicate\nwhich takes an integer input and generates an integer output that's\nthree larger.\n\nBecause Prolog predicates often follow a convention of having \"inputs\"\nbefore \"outputs\", many predicates can be applied and composed as\nfunctions as is.  This includes length/2, reverse/2, maplist/3,\nappend/3, etc.\n\n## Dicts\n\nAn SWI-Prolog 7 dictionary is considered a function from its keys to its values.  Applying the function to a non-existent key fails.\n\n    ?- writeln(words{1:one, 2:two, 3:three} $ 2).\n    two\n    ?- writeln(words{1:one, 2:two, 3:three} $ 4).\n    false.\n\nThis is similar to SWI Prolog's dot notation but doesn't throw an exception for missing keys.  Dicts as functions can be composed and applied just like other functions.\n\n\n## Arithmetic expressions of one variable\n\nAny arithmetic expression of a single variable can be applied and\ncomposed as a function.  For example, `2*_+3` is the function which\nmultiplies a number by two and then adds three.  Similarly,\n`sqrt(X)*X + X/2` is a function even though it uses the input in\nthree different places.\n\n## format/2 templates\n\nA format string acceptable as the first argument to format/2 can be\nused as a function.  It generates an atom, list of codes or string\nas output.\nThe template's type determines the output's type.  This offers a\npowerful string interpolation syntax visually similar to Python's.\n\nIn this next example, `X` might hold any of the values `codes`,\n`chars`, `number` or  `length`.\n\n    call('atom_~w' $ X, Atom, Term)\n\nOne might also use this interpolation syntax to build a file path:\n\n    Path = \"/home/~w/src/~w/.git/config\" $ [User, Project]\n\n## Tilde Terms\n\nA compound term with a single `~` argument is considered a function which takes no input values and produces an output at the `~` position.  For example,\n\n    atom(atom_string(~,\"hello world\")).\n\nproduces code that's equivalent to\n\n    atom_string(X,\"hello world\"),\n    atom(X).\n\nThis can be conveniently employed with arithmetic expressions.\n\n    length(List, ~ is X + Y).\n\nBecause tilde terms take no inputs, they can't be used with $/2 or of/2.\n\n# Defining functions\n\nAny term can behave as a function by defining additional clauses for\nthe multifile hook func:compile_function/4.  See the full\ndocumentation for greater detail.  In this example, we'll define a\nlist term as a function from a 0-based index to the corresponding\nelement of that list.\n\n    :- multifile func:compile_function/4.\n    func:compile_function(List, Index, Elem, nth0(Index, List, Elem)) :-\n        is_list(List).\n\nWe might use it to convert small integers into English words:\n\n    N = 2,\n    format('The number word is ~w~n', [zero,one,two,three] $ N).\n\nOne might imagine similar definitions for assoc lists, binary trees,\nhash tables, etc.\n\n# Installation\n\nUsing SWI-Prolog 6.3 or later:\n\n\n    $ swipl\n    1 ?- pack_install(func).\n\n\nSource code available and pull requests accepted on GitHub:\nhttps://github.com/mndrix/func\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmndrix%2Ffunc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmndrix%2Ffunc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmndrix%2Ffunc/lists"}