rfc:namespaces

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
rfc:namespaces [2008/09/15 01:19] – add issue regarding constants/class constants ambiguities jochemrfc:namespaces [2008/09/16 01:47] – test1.php's ouputs have one mistake shenkong
Line 35: Line 35:
  
 The following issues have been put forwards by various members of the php developers group and php users at large, the issues are covered in the following sections: The following issues have been put forwards by various members of the php developers group and php users at large, the issues are covered in the following sections:
-  - 1. global & namespaced code in one file+  - 1. **global & namespaced code in one file**
   - 2. define() & defined()   - 2. define() & defined()
   - 3. Autoload & functions   - 3. Autoload & functions
-  - 4. You can **use** anything+  - 4. You can use anything
   - 5. Importing NameSpace::*   - 5. Importing NameSpace::*
-  - 6. Static methods v. namespaced function ambiguities +  - 6. **Static methods v. namespaced function ambiguities** 
-  - 7. Class constants v. constants ambiguities +  - 7. **Class constants v. namespaced constants ambiguities** 
-  - 8. **use** and includes +  - 8. use and includes 
-  - 9. Importing functions +  - 9. **Importing functions** 
-  - 10. Name resolution order+  - 10. **Name resolution order**
   - 11. Keywords in namespace names   - 11. Keywords in namespace names
   - 12. Namespace must be first declaration in file   - 12. Namespace must be first declaration in file
   - 13. Namespaces aren't implemented like in ...   - 13. Namespaces aren't implemented like in ...
 +
 +
 +
  
 ==== 1. global & namespaced code in one file ==== ==== 1. global & namespaced code in one file ====
 currently one can declare multiple namespaces per file, but it is not possible to have code in the global scope in a file that declares namespaces, this is seen by some as an artificial limitation that forces some developers to change their project structures and as such breaks system that make use of (automated) source file concatenation (for performance reasons & distrubition), this is issue is being tackled in a seperate rfc and won't be covered here. (see [[rfc:namespacecurlies]])  currently one can declare multiple namespaces per file, but it is not possible to have code in the global scope in a file that declares namespaces, this is seen by some as an artificial limitation that forces some developers to change their project structures and as such breaks system that make use of (automated) source file concatenation (for performance reasons & distrubition), this is issue is being tackled in a seperate rfc and won't be covered here. (see [[rfc:namespacecurlies]]) 
    
 +
 +
 +----
 +
 ==== 2. define() & defined() ==== ==== 2. define() & defined() ====
 currently one can declare constants in namespaces (in the same way as can be done in classes) as well as using the **define()** function inside namespaced code, currently one can declare constants in namespaces (in the same way as can be done in classes) as well as using the **define()** function inside namespaced code,
Line 101: Line 108:
 <code> <code>
 defined('DEBUG'): YES (expect YES) defined('DEBUG'): YES (expect YES)
-defined('my::test::ns::DEBUG_2'): NO (expect YES)+defined('MY::TEST::NS::DEBUG_2'): NO (expect YES)
 defined('my::test::ns::DEBUG_2'): NO (expect NO) defined('my::test::ns::DEBUG_2'): NO (expect NO)
 defined('my::test::ns::debug_2'): NO (expect NO) defined('my::test::ns::debug_2'): NO (expect NO)
Line 213: Line 220:
   * which of the inconsistencies can be resolved through changes to the implementation?   * which of the inconsistencies can be resolved through changes to the implementation?
   * given the potential for confusion, and the potential difficulty of implementing a solution, is it worth keeping the ability to define constants (with **const**) directly in namespaces?    * given the potential for confusion, and the potential difficulty of implementing a solution, is it worth keeping the ability to define constants (with **const**) directly in namespaces? 
 +
 +
 +
 +----
  
 ==== 3. Autoload & functions ==== ==== 3. Autoload & functions ====
Line 318: Line 329:
  
  
-==== 4. You can 'use' anything ==== 
  
 +----
 +
 +==== 4. You can 'use' anything ====
 When trying to use an undefined class or function the engine will respond with a fatal error (after an attempt to autoload in the case of  When trying to use an undefined class or function the engine will respond with a fatal error (after an attempt to autoload in the case of 
 a class), this is not the case with the **use** statement <del>(although it does trigger autoloading if an autoloader is defined)</del>, this seems inconsistent and unhelpful, the expectation would be that an unresolvable **use** statement would give a fatal error, the following code tries to demonstrate the issue, a class), this is not the case with the **use** statement <del>(although it does trigger autoloading if an autoloader is defined)</del>, this seems inconsistent and unhelpful, the expectation would be that an unresolvable **use** statement would give a fatal error, the following code tries to demonstrate the issue,
Line 376: Line 389:
   * is it viable to implement?   * is it viable to implement?
   * what effect would included files have? would they need to be considered when implementing this?    * what effect would included files have? would they need to be considered when implementing this? 
 +
 +
 +
 +----
  
 ==== 5. Importing NameSpace::* ==== ==== 5. Importing NameSpace::* ====
Line 427: Line 444:
 **The question is:** should we allow importing of everything in a namespace or accept that people will use the above mentioned work-around (which I believe   **The question is:** should we allow importing of everything in a namespace or accept that people will use the above mentioned work-around (which I believe  
 probably will happen)? regardless one can consider this issue a philosophical one, rather than one caused by an unintentioned limitation in the namespace implementation. If importing of everything via a single **use** statement is added as engine functionality other issues are raised regarding what would occur with namespaced functions and constants. probably will happen)? regardless one can consider this issue a philosophical one, rather than one caused by an unintentioned limitation in the namespace implementation. If importing of everything via a single **use** statement is added as engine functionality other issues are raised regarding what would occur with namespaced functions and constants.
 +
 +
 +
 +----
  
 ==== 6. Static methods/namespaced function ambiguities ==== ==== 6. Static methods/namespaced function ambiguities ====
 +There is an abiguity, from the users point of view between static class method calls and namespaced function calls, essentially it is very difficult to determine (if at all) from the code, even given context, whether **TEST::what();** (from example1.php below) is a static method call or a namespaced function call. The statement could, in this case, be either, and which ever it is the other has been rendered unusable, the code below demonstrates:
 +
 +class.inc:
 +<code php>
 +<?php
 +class TEST {
 +    static function what()  { echo __FUNCTION__," in class\n"; }
 +    static function where() { echo __FUNCTION__," in class\n"; }
 +}
 +?>
 +</code>
 +
 +ns.inc:
 +<code php>
 +<?php
 +namespace TEST;
 +function what() { echo __FUNCTION__," in namespace\n"; }
 +?>
 +</code>
 +
 +example1.php:
 +<code php>
 +<?php
 +include './class.inc';
 +include './ns.inc';
 +TEST::what();
 +TEST::where();
 +?>
 +</code>
 +
 +output of example1.php (regardless of include order):
 +<code>
 +TEST::what in namespace
 +where in class
 +</code>
 +
 +There is no way to reference the static method **TEST::what()**, additionally because static method **TEST::where()** is reachable one is left with the potential that the namespaced include will break current code if a **where()** function is later defined in the **TEST** namespace. 
 +
 +//There is a need to disambiguate these two calls, and to be able to call both regardless of the existence of the other.//
 +
 +----
 +
 +==== 7. Class constants v. constants ambiguities ====
 +The same ambiguity that exists between static methods and namespaced functions also exists between class constants and namespaced constants.  
 +From the users point of view it not possible to determine, with any easy or certainty, from the code whether **TEST::MY_CONST_ONE** (from example1.php below) is a class constant or a namespaced constant. The statement could, in this case, be either, and which ever it is the other has been rendered unusable, the code below demonstrates:
 +
 +class.inc:
 +<code php>
 +<?php
 +class TEST {
 +    const MY_CNST_ONE = 'TEST class CONSTANT ONE';
 +    const MY_CNST_TWO = 'TEST class CONSTANT TWO';
 +}
 +?>
 +</code>
 +
 +ns.inc:
 +<code php>
 +<?php
 +namespace TEST;
 +const MY_CNST_ONE = 'TEST class CONSTANT ONE';
 +?>
 +
 +example1.php:
 +<code php>
 +<?php
 +include './class.inc';
 +include './ns.inc';
 +echo TEST::MY_CNST_ONE, "\n";
 +echo TEST::MY_CNST_TWO, "\n";
 +?>
 +</code>
 +
 +output of example1.php (regardless of include order):
 +<code>
 +TEST namespace CONSTANT ONE
 +TEST class CONSTANT TWO
 +</code>
 +
 +There is no way to reference the constant **MY_CNST_ONE** from class **TEST**, additionally because constant **MY_CNST_TWO** from class **TEST** is reachable one is left with the potential that the namespaced include will break current code if a constant **MY_CNST_TWO** is later defined in the TEST namespace, regardless it introduces confusion because one is it possible to retrieve constants from two different 'places' using the exact same prefix/syntax.
 +
 +//There is a need to disambiguate the constants, and to be able to reference both regardless of the existence of the other.// 
 +
  
-==== 7. **use** and includes ====+----
  
 +==== 8. **use** and includes ====
 Users are currently able and used to be able to include code, especially inside a loop, that makes use of the "includer's" variables and state in order to do something, very often this relates to some kind of templated output generation ... the reason to use an include file as opposed to a function often revolves around the issue of having alot of textual or HTML output which some find less well suited to being contained inside a function, additionally complex logic that would allow such an include file to be used in disparate circumstances would become messy in terms of function argument if a function was used instead. Users are currently able and used to be able to include code, especially inside a loop, that makes use of the "includer's" variables and state in order to do something, very often this relates to some kind of templated output generation ... the reason to use an include file as opposed to a function often revolves around the issue of having alot of textual or HTML output which some find less well suited to being contained inside a function, additionally complex logic that would allow such an include file to be used in disparate circumstances would become messy in terms of function argument if a function was used instead.
  
Line 446: Line 551:
 Chances are this is not a good idea, nonetheless details examples and documentation will probably be required in order to stem developer confusion, if nothing else confusion will limit uptake (as a rule users generally don't make use of functionality they either don't understand or misunderstand) Chances are this is not a good idea, nonetheless details examples and documentation will probably be required in order to stem developer confusion, if nothing else confusion will limit uptake (as a rule users generally don't make use of functionality they either don't understand or misunderstand)
  
-==== 8. Importing functions ==== 
  
-==== 9. Name resolution order ==== 
  
-==== 10. Keywords in namespace names ====+----
  
-==== 11. Namespace must be first declaration in file ====+==== 9. Importing functions ==== 
 +It is not currently possible to alias namespaced functions, making them inconsistent with namespaced classes, and forcing users that are working with namespaced functions to always prefix namespaced functions in order to use them. This seems like an artificial limitation that implies functions are a second-class after thought as far as namespaces are concerned, additionally php has never before dictated to users an **OO** over **procedural** style of coding, the current implementation of namespaces seems to imply that **OO** is inherently better.  
 + 
 +It is therefore not possible to override built in functions with functions imported from a namespace, which some people has expressed a desire to do ... most notably in the context of template engines, which generally strive to hide as much of the php's syntax from template developers [who generally don't program php] even though the template engine actually uses php syntax/code to expose it's functionality) ... forcing template developers to learn the intricacies of prefixing functions they employ (and there by having to realise that these may clash with static methods!) creates an unnecessary burden. 
 + 
 +Regardless, it should be possible to import a namespaced function into the current file and use it in the same way one has been accustomed to calling functions. 
 +The following examples tries to demonstrate the issue: 
 + 
 +ns_funcs.inc: 
 +<code php> 
 +<?php 
 +namespace MY::TEST::NS; 
 +function foo() { echo "Hello World!\n";
 +?> 
 +</code> 
 + 
 +example1.php: 
 +<code php> 
 +<?php 
 +include './ns_funcs.php'; 
 +// use MY::TEST::NS::foo; 
 +use MY::TEST::NS; 
 +NS::foo(); 
 +MY::TEST::NS::foo(); 
 +?> 
 +</code> 
 + 
 +output from example1.php: 
 +<code> 
 +Hello World! 
 +Hello World! 
 +</code> 
 + 
 +example2.php: 
 +<code php> 
 +<?php 
 +include './ns_funcs.php'; 
 +use MY::TEST::NS::foo; 
 +foo(); 
 +?> 
 +</code> 
 + 
 +output from example2.php: 
 +<code> 
 +Fatal error: Call to undefined function foo() in <PATH>/example2.php on line 4 
 +</code> 
 + 
 + 
 + 
 +---- 
 + 
 +==== 10. Name resolution order ==== 
 + 
 + 
 + 
 +---- 
 + 
 +==== 11. Keywords in namespace names ==== 
 +It is stated that namespace names serve simply as string replacements to unqualified [namespaced] class, function and constant names, which suggests that '::' that is often seen in the namespace names of example code is essentially meaningless, merely offering a visual aid to the user of namespaced code as to the intended structure of the entities defined within, as opposed to actually defining a semantic nesting of namespaced code: 
 + 
 +example1.php: 
 +<code php> 
 +<?php 
 +namespace MY::PROJECT; 
 +class App {} 
 +namespace MY::PROJECT::DB; 
 +class DB {} 
 +namespace MY::PROJECT::MVC; 
 +class Model {} 
 +class View {} 
 +class Controller {} 
 +namespace MY::PROJECT::MVC::MODELS; 
 +class Product {} 
 +class Customer {} 
 +class Order {} 
 +?> 
 +</code> 
 + 
 +the preceeding example offers, according to current documentation, syntactic sugar that denotes how a project/codebase is structured without actually creating that structure. Yet the engine seems to actually parse namespace name piece by piece (e.g. 'MY', 'PROJECT', 'MVC' and 'MODELS') rather than treating the namespace name as an arbitrary string, the following demonstrates what happens when a keyword is incoporated: 
 + 
 +example2.php: 
 +<code php> 
 +<?php 
 +namespace MY::PROJECT::STATIC::STUFF; 
 +// some code 
 +?> 
 +</code> 
 + 
 +output of example2.php: 
 +<code> 
 +Parse error: syntax error, unexpected T_STATIC, expecting T_STRING in <PATH>/example2.php on line 2 
 +</code> 
 + 
 +Essentially the engine is smarter about namespace names and aliases thereof than it is letting on, it's an almost certainty that the only issue here is lack of or somewhat misleading documentation (It's also fairly clear that this lends itself to a nested namespace implementation if that is ever seriously proposed). Below is a small example script demonstrating the engine's 'smarts'
 + 
 +example3.php: 
 +<code php> 
 +<?php 
 +namespace MY::TEST::NS; 
 +class hi {} 
 + 
 +namespace MY__TEST__NS; 
 +class hi {} 
 + 
 +namespace THIRD; 
 +use MY::TEST; 
 +use MY::TEST::NS; 
 + 
 +$a = new TEST::NS::hi;     // 'for' $a and $b the engine is smart enough to do MY::TEST::NS::hi, 
 +$b = new NS::hi;           // something that can't be done with MY__TEST__NS. 
 +$c = new MY__TEST__NS::hi;  
 +var_dump($a, $b, $c); 
 +?> 
 +</code> 
 + 
 +output of example3.php: 
 +<code> 
 +object(MY::TEST::NS::hi)#1 (0) { 
 +
 +object(MY::TEST::NS::hi)#2 (0) { 
 +
 +object(MY__TEST__NS::hi)#3 (0) { 
 +
 +</code> 
 + 
 + 
 + 
 +---- 
 + 
 +==== 12. Namespace must be first declaration in file ====
 Currently if you wish to declare one or more namespaces in a file nothing may preceed the initial namespace declaration, __with the exception of white-space & comments between the initial php parser tag (**<?php**) and the initial namespace declaration__ (one can include as many comment blocks as one want's preceeding the initial namespace declaration in a file) . Currently if you wish to declare one or more namespaces in a file nothing may preceed the initial namespace declaration, __with the exception of white-space & comments between the initial php parser tag (**<?php**) and the initial namespace declaration__ (one can include as many comment blocks as one want's preceeding the initial namespace declaration in a file) .
  
Line 499: Line 731:
 </code> </code>
  
-==== 12. Namespaces aren't implemented like in ... ====+ 
 + 
 +---- 
 + 
 +==== 13. Namespaces aren't implemented like in ... ====
 PHP is not <insert your favorite language here>. Granted this is not an issue, but some of you reading this probably need something to smile about after reading the items above! PHP is not <insert your favorite language here>. Granted this is not an issue, but some of you reading this probably need something to smile about after reading the items above!
 +
 +
 +
  
 ===== Patches & Proposal ===== ===== Patches & Proposal =====
Line 506: Line 745:
 additionally a number of patches have already been made available, these are listed below: additionally a number of patches have already been made available, these are listed below:
  
 +==== Issue's 6 & 7 ====
   * http://pear.php.net/~greg/resolvensfuncconst.patch.txt (Greg Beaver)   * http://pear.php.net/~greg/resolvensfuncconst.patch.txt (Greg Beaver)
-This patch addresses the issues regarding, as defined in issue ??+This patch addresses the issues regarding resolution ambiguities, as defined in **issue 6. "Static methods/namespaced function ambiguities"** and **issue 7. "Class constants v. constants ambiguities"**.
  
 To quote the author from his original post regarding this patch: To quote the author from his original post regarding this patch:
Line 518: Line 758:
 > >
 > If a fully qualified name is prefixed with function:: or const:: it will only check the namespace function/const.  Here is a test demonstrating how it works: > If a fully qualified name is prefixed with function:: or const:: it will only check the namespace function/const.  Here is a test demonstrating how it works:
- +> 
-ns_071.inc: +ns_071.inc: 
-<code php>+<code php>
 <?php <?php
 namespace foo; namespace foo;
Line 533: Line 773:
 ?> ?>
 </code> </code>
-ns_071.phpt: +ns_071.phpt: 
-<code php>+<code php>
 --TEST-- --TEST--
 071: name conflict, function/static method, constant/class constant 071: name conflict, function/static method, constant/class constant
Line 566: Line 806:
 </code> </code>
  
 +==== Issue 9 ====
   * http://pear.php.net/~greg/usefunctions.patch.txt (Greg Beaver)   * http://pear.php.net/~greg/usefunctions.patch.txt (Greg Beaver)
-This patch addresses the issues regarding the inability to alias functions to simple names, as defined in issue ??+This patch addresses the issues regarding the inability to alias functions to simple names, as defined in **issue 9. "Importing functions"**
  
 +
 +==== Issue 12 ====
   * http://pear.php.net/~greg/inline_html.patch.txt (Greg Beaver)    * http://pear.php.net/~greg/inline_html.patch.txt (Greg Beaver) 
-This patch addresses the inability to include [html] output prior to the first **<?php** tag, in a namespaced file, as defined in **issue 11. Namespace must be first declaration in file**  +This patch addresses the inability to include [html] output prior to the first **<?php** tag, in a namespaced file, as defined in **issue 12"Namespace must be first declaration in file"**  
  
-===== Miscellaneous =====+To quote the author from his original post regarding this patch: 
  
 +> This is a simple patch that allows files like this to work without parse error.:
 +
 +> main.php:
 +> <code php>
 +<html>
 +<head>
 +<title>template example</title>
 +</head>
 +<body>
 +<?php
 +namespace my::template;
 + 
 +// stuff
 +
 +?>
 +</body>
 +</html>
 +</code>
 +
 +===== Miscellaneous =====
   * [[http://docs.php.net/manual/en/language.namespaces.php|Most current publicly available namespace documentation]]   * [[http://docs.php.net/manual/en/language.namespaces.php|Most current publicly available namespace documentation]]
   * An RFC discussing namespaces for internal classes exists (see: [[[rfc:namespaces-for-internal-classes]]])   * An RFC discussing namespaces for internal classes exists (see: [[[rfc:namespaces-for-internal-classes]]])
   * A scratchpad document is being worked on to gather namespace 'best practices' which will hopefully be incorporated into the official manual at some stage (see: [[doc:scratchpad:namespaces]])    * A scratchpad document is being worked on to gather namespace 'best practices' which will hopefully be incorporated into the official manual at some stage (see: [[doc:scratchpad:namespaces]]) 
 +
 +
 +
  
 ===== Discussions past & present ===== ===== Discussions past & present =====
 +Below is a list of links to internals@lists.php.net thread that discuss (amongst others things) namespaces, the list is in reverse chronological order (hopefully) based on the initial post to the given thread and only lists discussion that have occurred in 2008:
 +
 +  * [[php-internals@122125176711750|the namespace war]]
 +  * [[php-internals@122124674902629|PATCH: allow T_INLINE_HTML before T_NAMESPACE]]
 +  * [[php-internals@122118945204074|PATCH: updated resolve function/const conflict between namespace/class]]
 +  * [[php-internals@122118574632627|PATCH: add support for functions to use]]
 +  * [[php-internals@122126001625094|Please don't start 10 threads a day about the Namespace support]]
 +  * [[php-internals@122114969907530|Scoping of "use" statements and a strategy for 5.3/6.0 release of namespace]]
 +  * [[php-internals@122110981102381|PATCH: resolve const/function namespace conflicts (Liz take note)]]
 +  * [[php-internals@122098797532195|namespace function/static method/class constant conflict resolution]]
 +  * [[php-internals@122018993030061|namespace RFC]]
 +  * [[php-internals@121920359817682|Namespace Global User Function Calls]]
 +  * [[php-internals@121776665630615|Inconsistencies in 5.3]]
 +  * [[php-internals@121626223101585|questions about namespaces, functions vs. closures]]
 +  * [[php-internals@121615179414749|Include/require into namespace]]
 +  * [[php-internals@121614847408006|Namespace problem?]]
 +  * [[php-internals@121502894019535|towards a 5.3 release]]
 +  * [[php-internals@121447143022557|How bad would it be to say/enforce that namespacing can only apply to classes and not ...]]
 +  * [[php-internals@121397701404954|simple solution to another namespace conundrum?]]
 +  * [[php-internals@121233666301819|multiple use]]
 +  * [[php-internals@121223589228439|Alternative to multiple namespaces per file]]
 +  * [[php-internals@121199212705823|Name resolution rules]]
 +  * [[php-internals@121079120018378|5.3 Namespace resolution rules suggestions]]
 +  * [[php-internals@121071258907404|5.3 and reflection]]
 +  * [[php-internals@120742574008363|namespace implementation (irritating warning and autoload)]]
 +  * [[php-internals@120613563032212|RFC: Namespace syntax decision]]
 +  * [[php-internals@120429739728318|PHP 5.3 Autoload+Namespaces+Functions incorret (atleast wierd) behaviour.]]
 +  * [[php-internals@120018255502021|Namespace & Type Hinting Summaries?]]
 +  * [[php-internals@119992382220241|Set default namespace]]
 +  * [[php-internals@119874502923978|Suggestion: Namespace implementation]]
 +
 +//Nothing has been filtered on the basis of relevance BUT some threads may not be listed due to the 'limitations' of the marc.info search functionality!//
 +
 +
  
-**//I will list a set of links to archives of all namespace discussions (on internals mailing list) once descriptions and repro-code of the listed issues are inplace//** 
  
 ===== Additional Commentary ===== ===== Additional Commentary =====
 the articles & blog posts listed here are (hopefully) in reverse chronological order, please note that older items may no longer be relevant as the implementation has changed since the time the item was published: the articles & blog posts listed here are (hopefully) in reverse chronological order, please note that older items may no longer be relevant as the implementation has changed since the time the item was published:
  
 +  - [[http://forge.typo3.org/wiki/flow3-overview/Notes_on_using_PHP_namespaces|Typo3v5 - Flow3: Notes on using PHP namespaces]]
   - [[http://elizabethmariesmith.com/2008/09/my-five-well-four-and-one-half-issues-with-namespaces/#comments|Elizabeth Smith: four-and-one-half-issues]]   - [[http://elizabethmariesmith.com/2008/09/my-five-well-four-and-one-half-issues-with-namespaces/#comments|Elizabeth Smith: four-and-one-half-issues]]
   - [[http://pooteeweet.org/blog/0/1288#m1288|Lukas Kahwe Smith: Who is using namespaces in PHP already? (including feedback)]]   - [[http://pooteeweet.org/blog/0/1288#m1288|Lukas Kahwe Smith: Who is using namespaces in PHP already? (including feedback)]]
Line 603: Line 903:
 for the really keen ones amongst us, knock yourself out: for the really keen ones amongst us, knock yourself out:
  
-  - [[http://search.yahoo.com/search?p=php+namespaces|Search Yahoo]] +  - [[http://search.yahoo.com/search?p=php+namespaces|Search Yahoo for 'php namespaces']] 
-  - [[http://www.google.com/search?q=php+namespaces|Search Google]]+  - [[http://www.google.com/search?q=php+namespaces|Search Google for 'php namespaces']]
rfc/namespaces.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1