{
  "category": "Our 10 featured functions",
  "display_name": "IF",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.IF",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 64 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 64 recorded answers",
    "workbook_corpus": {
      "cells": 64,
      "matched": 64
    }
  },
  "implementations": [
    {
      "commit": "9e1884369a678158dd82d3d74188daf986995e87",
      "flavour": "excel-compatibility-candidate",
      "language": "Rust",
      "name": "CalcFunc",
      "own_code": [
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/logical.rs#L85-L97",
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/logical.rs#L117-L138"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/logical.rs#L85-L97",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 64 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.IF.json",
  "name": "IF",
  "notes": [],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n### Relationships\n\n\n- **`IFS`** replaces long `IF(a, x, IF(b, y, IF(c, z, ...)))` chains with a flat condition/value\n  list. It is not a superseding pair — Microsoft retains both and they are not equivalent at the\n  edges: `IFS` returns `#N/A` when nothing matches, where a nested `IF` chain returns its innermost\n  false branch.\n- **`SWITCH`** compares one expression against a list of candidate values rather than evaluating\n  independent conditions.\n- **`IFERROR` and `IFNA`** branch on error-ness rather than on truth, and they are what people\n  reach for after discovering that `IF` returns errors verbatim.\n- **`CHOOSE`** selects by 1-based index rather than by condition.\n- **`AND` / `OR`** are the usual condition builders; note that they evaluate all their arguments,\n  so `IF(AND(...), ...)` does not short-circuit the way a programmer expects.\n- Readers confuse `IF` with `IFS` most often, and with `SUMIF`/`COUNTIF` second most often — the\n  latter are aggregates whose `IF` is a criteria filter, not a branch.\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n1. **Laziness is observable.** Evaluating both branches and then discarding one changes behaviour\n   whenever a branch is expensive, volatile, or returns a callable. The call model classifies `IF`\n   as a lazy branch selector for that reason; an eager implementation is not merely slower.\n3. **Reference awareness is not optional.** Because `IF` sees live references, the branch it does\n   not take is never dereferenced. An implementation that resolves arguments before dispatch will\n   produce reference-resolution errors that Excel would never raise.\n4. **Shape first, then select.** With an array condition, the result shape is the condition's\n   shape; branches are materialised against it. Deciding shape after selection gives the wrong\n   answer whenever one branch is scalar and the other is not.\n\n\n",
    "quirks": "\n### Result and edge cases\n\n\nReturns whatever kind the selected branch carries: `Number`, `Text`, `Logical`, `Error`, or an\narray.\n\n- **Condition is an empty cell.** Reads as false; the false branch is taken.\n- **Condition is an error.** Propagates; neither branch is selected.\n- **Branch is an error.** Returned as-is. `IF(TRUE, 1/0, 0)` is `#DIV/0!`.\n\n\n\n### Errors\n\n\n| Error | Condition |\n|---|---|\n| `#VALUE!` | `logical_test` is text that does not read as a number. |\n| any incoming error | An error in `logical_test` propagates; an error in the *selected* branch is returned unchanged. |\n| `#NAME?` | Documented by Microsoft as the symptom of a misspelled formula — a parse-level, not an `IF`-level, failure. |\n\n",
    "sources": "- Handbook call-model chapters\n  [01 The value universe](../model/01-value-universe.md),\n  [02 Coercion and lifting](../model/02-coercion-and-lifting.md),\n  [03 The call pipeline](../model/03-call-pipeline.md).\n- `data/functions/FUNC.IF.json` — arity, classification axes, localized names.\n\n\n",
    "version-differences": "No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.",
    "what-it-does": "\n`IF` selects between two values according to the truthiness of a condition, and returns the\nselected value **verbatim** — it does not coerce, reshape, or inspect what it returns.\n\nThe rule:\n\n1. Prepare `logical_test` and reduce it to a truth value. A `Logical` is itself; a `Number` is\n   false when exactly 0 and true otherwise; an `Empty` or omitted condition reads as false; text\n   that does not read as a number fails; an error propagates.\n2. If the condition is true, return `value_if_true`. Otherwise return `value_if_false`.\n3. Only the selected branch's value is delivered. `IF` is classified as a **lazy branch selector**\n   in the call model: the unselected branch does not contribute to the result, which is why\n   `IF(TRUE, lambda)` can pass a callable value through unchanged\n   ([chapter 03](../model/03-call-pipeline.md), \"Functions that step outside the plain pipeline\").\n\nTwo structural properties follow from \"verbatim\", and they are what make `IF` more than sugar:\n\n- **`IF` is kind-preserving.** If the selected branch is text, `IF` returns text; if it is an\n  error, `IF` returns that error. `IF` is not an error handler — `IFERROR` is.\n\n\n\n### Arguments\n\n\n`IF(logical_test, value_if_true, [value_if_false])`\n\n- **`logical_test`** — required. A condition, or anything that can be reduced to one. The most\n  common misunderstanding lives here: `logical_test` is *not* required to be a `Logical`. Numbers\n  work, and the zero test is exact.\n\n\nThere is a third case that is neither \"supplied\" nor \"omitted\": a **present but empty slot**, as in\n`IF(cond, 1, )`. Microsoft's page addresses this obliquely under common problems, noting that a\nmissing argument for either branch shows as `0` in the cell. So the documented reading is that an\nempty slot yields `0` while a genuinely absent third argument is undocumented — and the reference\nengine distinguishes `Missing` from `Empty` at exactly this seam\n([chapter 01](../model/01-value-universe.md), \"Missing versus Empty\"). Whether Excel's two cases\nreally differ is listed below as unchecked, and it is the most useful probe on the page.\n\n\n"
  },
  "signature": {
    "display": "IF(logical_test, value_if_true, [value_if_false])",
    "parameters": [
      {
        "description": "Condition evaluation drives the branch selection.",
        "name": "logical_test",
        "optional": false,
        "repeats": false
      },
      {
        "description": "Returned when the logical test evaluates truthy.",
        "name": "value_if_true",
        "optional": false,
        "repeats": false
      },
      {
        "description": "Optional false branch; omission follows the current baseline IF defaulting rules.",
        "name": "value_if_false",
        "optional": true,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 3,
        "min": 2
      },
      "category": "Our 10 featured functions",
      "classification": {
        "arg_preparation_profile": "RefsVisibleInAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "SelectorBranch",
        "fec_dependency_profile": "None",
        "host_interaction_class": "None",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": "The first widened tranche uses IF as the control-flow anchor for mixed witness rollout.",
        "short": "One of two values, chosen by whether a condition is TRUE",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Use this function to return one value if a condition is true and another value if it's false. Here's a video about using the IF function .",
        "microsoft_url": "https://support.microsoft.com/en-us/office/if-function-69aed7c9-4e8a-4755-a9bc-aa8bbff73be2"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "IF"
        },
        {
          "locale": "bg-BG",
          "name": "IF"
        },
        {
          "locale": "cs-CZ",
          "name": "KDYŽ"
        },
        {
          "locale": "da-DK",
          "name": "HVIS"
        },
        {
          "locale": "de-DE",
          "name": "WENN"
        },
        {
          "locale": "el-GR",
          "name": "IF"
        },
        {
          "locale": "en-AU",
          "name": "IF"
        },
        {
          "locale": "en-GB",
          "name": "IF"
        },
        {
          "locale": "en-US",
          "name": "IF"
        },
        {
          "locale": "es-ES",
          "name": "SI"
        },
        {
          "locale": "et-EE",
          "name": "Funktsioon IF"
        },
        {
          "locale": "fi-FI",
          "name": "JOS"
        },
        {
          "locale": "fr-FR",
          "name": "SI"
        },
        {
          "locale": "he-IL",
          "name": "IF"
        },
        {
          "locale": "hr-HR",
          "name": "IF"
        },
        {
          "locale": "hu-HU",
          "name": "HA"
        },
        {
          "locale": "id-ID",
          "name": "IF"
        },
        {
          "locale": "it-IT",
          "name": "SE"
        },
        {
          "locale": "ja-JP",
          "name": "IF"
        },
        {
          "locale": "ko-KR",
          "name": "IF"
        },
        {
          "locale": "lt-LT",
          "name": "IF"
        },
        {
          "locale": "lv-LV",
          "name": "IF"
        },
        {
          "locale": "nb-NO",
          "name": "HVIS"
        },
        {
          "locale": "nl-NL",
          "name": "ALS"
        },
        {
          "locale": "pl-PL",
          "name": "JEŻELI"
        },
        {
          "locale": "pt-BR",
          "name": "SE"
        },
        {
          "locale": "pt-PT",
          "name": "SE"
        },
        {
          "locale": "ro-RO",
          "name": "IF"
        },
        {
          "locale": "ru-RU",
          "name": "ЕСЛИ"
        },
        {
          "locale": "sk-SK",
          "name": "IF"
        },
        {
          "locale": "sl-SI",
          "name": "IF"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "IF"
        },
        {
          "locale": "sv-SE",
          "name": "OM"
        },
        {
          "locale": "th-TH",
          "name": "IF"
        },
        {
          "locale": "tr-TR",
          "name": "EĞER"
        },
        {
          "locale": "uk-UA",
          "name": "IF"
        },
        {
          "locale": "vi-VN",
          "name": "IF"
        },
        {
          "locale": "zh-CN",
          "name": "IF"
        },
        {
          "locale": "zh-HK",
          "name": "IF"
        },
        {
          "locale": "zh-TW",
          "name": "IF"
        }
      ],
      "signature": {
        "display": "IF(logical_test, value_if_true, [value_if_false])",
        "parameters": [
          {
            "description": "Condition evaluation drives the branch selection.",
            "name": "logical_test",
            "optional": false,
            "repeats": false
          },
          {
            "description": "Returned when the logical test evaluates truthy.",
            "name": "value_if_true",
            "optional": false,
            "repeats": false
          },
          {
            "description": "Optional false branch; omission follows the current baseline IF defaulting rules.",
            "name": "value_if_false",
            "optional": true,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "IF",
      "version_marker": null,
      "xlcall": null
    },
    "microsoft": "https://support.microsoft.com/en-us/office/if-function-69aed7c9-4e8a-4755-a9bc-aa8bbff73be2"
  },
  "try_it": {
    "formula": "=IF(2>1,\"yes\",\"no\")"
  },
  "url": "https://handbook.dnacalc.com/functions/IF.html",
  "variants": [],
  "versions": []
}